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 565 ierr = PetscOptionsName("-pc_hypre_boomeramg_print_statistics","Print statistics","None",&flg);CHKERRQ(ierr); 566 if (flg) { 567 int level=3; 568 jac->printstatistics = PETSC_TRUE; 569 ierr = PetscOptionsInt("-pc_hypre_boomeramg_print_statistics","Print statistics","None",level,&level,PETSC_NULL);CHKERRQ(ierr); 570 ierr = HYPRE_BoomerAMGSetPrintLevel(jac->hsolver,level);CHKERRQ(ierr); 571 ierr = HYPRE_BoomerAMGSetDebugFlag(jac->hsolver,level);CHKERRQ(ierr); 572 } 573 574 ierr = PetscOptionsTruth( "-pc_hypre_boomeramg_nodal_coarsen", "HYPRE_BoomerAMGSetNodal()", "None", PETSC_FALSE, &tmp_truth, &flg);CHKERRQ(ierr); 575 if (flg && tmp_truth) { 576 jac->nodal_coarsen = 1; 577 ierr = HYPRE_BoomerAMGSetNodal(jac->hsolver,1);CHKERRQ(ierr); 578 } 579 580 ierr = PetscOptionsTruth( "-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg);CHKERRQ(ierr); 581 if (flg && tmp_truth) { 582 PetscInt tmp_int; 583 ierr = PetscOptionsInt( "-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None",jac->nodal_relax_levels,&tmp_int,&flg);CHKERRQ(ierr); 584 if (flg) jac->nodal_relax_levels = tmp_int; 585 ierr = HYPRE_BoomerAMGSetSmoothType(jac->hsolver,6);CHKERRQ(ierr); 586 ierr = HYPRE_BoomerAMGSetDomainType(jac->hsolver,1);CHKERRQ(ierr); 587 ierr = HYPRE_BoomerAMGSetOverlap(jac->hsolver,0);CHKERRQ(ierr); 588 ierr = HYPRE_BoomerAMGSetSmoothNumLevels(jac->hsolver,jac->nodal_relax_levels);CHKERRQ(ierr); 589 } 590 591 ierr = PetscOptionsTail();CHKERRQ(ierr); 592 PetscFunctionReturn(0); 593 } 594 595 #undef __FUNCT__ 596 #define __FUNCT__ "PCApplyRichardson_HYPRE_BoomerAMG" 597 static PetscErrorCode PCApplyRichardson_HYPRE_BoomerAMG(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its) 598 { 599 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 600 PetscErrorCode ierr; 601 602 PetscFunctionBegin; 603 ierr = HYPRE_BoomerAMGSetMaxIter(jac->hsolver,its*jac->maxiter);CHKERRQ(ierr); 604 ierr = HYPRE_BoomerAMGSetTol(jac->hsolver,PetscMin(rtol,jac->tol));CHKERRQ(ierr); 605 jac->applyrichardson = PETSC_TRUE; 606 ierr = PCApply_HYPRE(pc,b,y);CHKERRQ(ierr); 607 jac->applyrichardson = PETSC_FALSE; 608 ierr = HYPRE_BoomerAMGSetTol(jac->hsolver,jac->tol);CHKERRQ(ierr); 609 ierr = HYPRE_BoomerAMGSetMaxIter(jac->hsolver,jac->maxiter);CHKERRQ(ierr); 610 PetscFunctionReturn(0); 611 } 612 613 614 #undef __FUNCT__ 615 #define __FUNCT__ "PCView_HYPRE_BoomerAMG" 616 static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc,PetscViewer viewer) 617 { 618 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 619 PetscErrorCode ierr; 620 PetscTruth iascii; 621 622 PetscFunctionBegin; 623 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 624 if (iascii) { 625 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG preconditioning\n");CHKERRQ(ierr); 626 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Cycle type %s\n",HYPREBoomerAMGCycleType[jac->cycletype]);CHKERRQ(ierr); 627 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Maximum number of levels %d\n",jac->maxlevels);CHKERRQ(ierr); 628 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Maximum number of iterations PER hypre call %d\n",jac->maxiter);CHKERRQ(ierr); 629 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Convergence tolerance PER hypre call %G\n",jac->tol);CHKERRQ(ierr); 630 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Threshold for strong coupling %G\n",jac->strongthreshold);CHKERRQ(ierr); 631 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Interpolation truncation factor %G\n",jac->truncfactor);CHKERRQ(ierr); 632 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Interpolation: max elements per row %d\n",jac->pmax);CHKERRQ(ierr); 633 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Number of levels of aggressive coarsening %d\n",jac->agg_nl);CHKERRQ(ierr); 634 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Number of paths for aggressive coarsening %d\n",jac->agg_num_paths);CHKERRQ(ierr); 635 636 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Maximum row sums %G\n",jac->maxrowsum);CHKERRQ(ierr); 637 638 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Sweeps down %d\n",jac->gridsweeps[0]);CHKERRQ(ierr); 639 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Sweeps up %d\n",jac->gridsweeps[1]);CHKERRQ(ierr); 640 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Sweeps on coarse %d\n",jac->gridsweeps[2]);CHKERRQ(ierr); 641 642 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Relax down %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[0]]);CHKERRQ(ierr); 643 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Relax up %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[1]]);CHKERRQ(ierr); 644 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Relax on coarse %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[2]]);CHKERRQ(ierr); 645 646 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Relax weight (all) %G\n",jac->relaxweight);CHKERRQ(ierr); 647 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Outer relax weight (all) %G\n",jac->outerrelaxweight);CHKERRQ(ierr); 648 649 if (jac->relaxorder) { 650 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Using CF-relaxation\n");CHKERRQ(ierr); 651 } else { 652 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Not using CF-relaxation\n");CHKERRQ(ierr); 653 } 654 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Measure type %s\n",HYPREBoomerAMGMeasureType[jac->measuretype]);CHKERRQ(ierr); 655 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Coarsen type %s\n",HYPREBoomerAMGCoarsenType[jac->coarsentype]);CHKERRQ(ierr); 656 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Interpolation type %s\n",HYPREBoomerAMGInterpType[jac->interptype]);CHKERRQ(ierr); 657 if (jac->nodal_coarsen) { 658 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Using nodal coarsening (with HYPRE_BOOMERAMGSetNodal())\n");CHKERRQ(ierr); 659 } 660 if (jac->nodal_relax) { 661 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Using nodal relaxation via Schwarz smoothing on levels %d\n",jac->nodal_relax_levels);CHKERRQ(ierr); 662 } 663 } 664 PetscFunctionReturn(0); 665 } 666 667 /* --------------------------------------------------------------------------------------------*/ 668 #undef __FUNCT__ 669 #define __FUNCT__ "PCSetFromOptions_HYPRE_ParaSails" 670 static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc) 671 { 672 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 673 PetscErrorCode ierr; 674 int indx; 675 PetscTruth flag; 676 const char *symtlist[] = {"nonsymmetric","SPD","nonsymmetric,SPD"}; 677 678 PetscFunctionBegin; 679 ierr = PetscOptionsHead("HYPRE ParaSails Options");CHKERRQ(ierr); 680 ierr = PetscOptionsInt("-pc_hypre_parasails_nlevels","Number of number of levels","None",jac->nlevels,&jac->nlevels,0);CHKERRQ(ierr); 681 ierr = PetscOptionsReal("-pc_hypre_parasails_thresh","Threshold","None",jac->threshhold,&jac->threshhold,&flag);CHKERRQ(ierr); 682 if (flag) { 683 ierr = HYPRE_ParaSailsSetParams(jac->hsolver,jac->threshhold,jac->nlevels);CHKERRQ(ierr); 684 } 685 686 ierr = PetscOptionsReal("-pc_hypre_parasails_filter","filter","None",jac->filter,&jac->filter,&flag);CHKERRQ(ierr); 687 if (flag) { 688 ierr = HYPRE_ParaSailsSetFilter(jac->hsolver,jac->filter);CHKERRQ(ierr); 689 } 690 691 ierr = PetscOptionsReal("-pc_hypre_parasails_loadbal","Load balance","None",jac->loadbal,&jac->loadbal,&flag);CHKERRQ(ierr); 692 if (flag) { 693 ierr = HYPRE_ParaSailsSetLoadbal(jac->hsolver,jac->loadbal);CHKERRQ(ierr); 694 } 695 696 ierr = PetscOptionsTruth("-pc_hypre_parasails_logging","Print info to screen","None",(PetscTruth)jac->logging,(PetscTruth*)&jac->logging,&flag);CHKERRQ(ierr); 697 if (flag) { 698 ierr = HYPRE_ParaSailsSetLogging(jac->hsolver,jac->logging);CHKERRQ(ierr); 699 } 700 701 ierr = PetscOptionsTruth("-pc_hypre_parasails_reuse","Reuse nonzero pattern in preconditioner","None",(PetscTruth)jac->ruse,(PetscTruth*)&jac->ruse,&flag);CHKERRQ(ierr); 702 if (flag) { 703 ierr = HYPRE_ParaSailsSetReuse(jac->hsolver,jac->ruse);CHKERRQ(ierr); 704 } 705 706 ierr = PetscOptionsEList("-pc_hypre_parasails_sym","Symmetry of matrix and preconditioner","None",symtlist,3,symtlist[0],&indx,&flag);CHKERRQ(ierr); 707 if (flag) { 708 jac->symt = indx; 709 ierr = HYPRE_ParaSailsSetSym(jac->hsolver,jac->symt);CHKERRQ(ierr); 710 } 711 712 ierr = PetscOptionsTail();CHKERRQ(ierr); 713 PetscFunctionReturn(0); 714 } 715 716 #undef __FUNCT__ 717 #define __FUNCT__ "PCView_HYPRE_ParaSails" 718 static PetscErrorCode PCView_HYPRE_ParaSails(PC pc,PetscViewer viewer) 719 { 720 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 721 PetscErrorCode ierr; 722 PetscTruth iascii; 723 const char *symt = 0;; 724 725 PetscFunctionBegin; 726 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 727 if (iascii) { 728 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails preconditioning\n");CHKERRQ(ierr); 729 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: nlevels %d\n",jac->nlevels);CHKERRQ(ierr); 730 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: threshold %G\n",jac->threshhold);CHKERRQ(ierr); 731 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: filter %G\n",jac->filter);CHKERRQ(ierr); 732 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: load balance %G\n",jac->loadbal);CHKERRQ(ierr); 733 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: reuse nonzero structure %s\n",PetscTruths[jac->ruse]);CHKERRQ(ierr); 734 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: print info to screen %s\n",PetscTruths[jac->logging]);CHKERRQ(ierr); 735 if (!jac->symt) { 736 symt = "nonsymmetric matrix and preconditioner"; 737 } else if (jac->symt == 1) { 738 symt = "SPD matrix and preconditioner"; 739 } else if (jac->symt == 2) { 740 symt = "nonsymmetric matrix but SPD preconditioner"; 741 } else { 742 SETERRQ1(PETSC_ERR_ARG_WRONG,"Unknown HYPRE ParaSails symmetric option %d",jac->symt); 743 } 744 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: %s\n",symt);CHKERRQ(ierr); 745 } 746 PetscFunctionReturn(0); 747 } 748 /* ---------------------------------------------------------------------------------*/ 749 750 EXTERN_C_BEGIN 751 #undef __FUNCT__ 752 #define __FUNCT__ "PCHYPREGetType_HYPRE" 753 PetscErrorCode PETSCKSP_DLLEXPORT PCHYPREGetType_HYPRE(PC pc,const char *name[]) 754 { 755 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 756 757 PetscFunctionBegin; 758 *name = jac->hypre_type; 759 PetscFunctionReturn(0); 760 } 761 EXTERN_C_END 762 763 EXTERN_C_BEGIN 764 #undef __FUNCT__ 765 #define __FUNCT__ "PCHYPRESetType_HYPRE" 766 PetscErrorCode PETSCKSP_DLLEXPORT PCHYPRESetType_HYPRE(PC pc,const char name[]) 767 { 768 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 769 PetscErrorCode ierr; 770 PetscTruth flag; 771 772 PetscFunctionBegin; 773 if (jac->hypre_type) { 774 ierr = PetscStrcmp(jac->hypre_type,name,&flag);CHKERRQ(ierr); 775 if (!flag) SETERRQ(PETSC_ERR_ORDER,"Cannot reset the HYPRE preconditioner type once it has been set"); 776 PetscFunctionReturn(0); 777 } else { 778 ierr = PetscStrallocpy(name, &jac->hypre_type);CHKERRQ(ierr); 779 } 780 781 jac->maxiter = PETSC_DEFAULT; 782 jac->tol = PETSC_DEFAULT; 783 jac->printstatistics = PetscLogPrintInfo; 784 785 ierr = PetscStrcmp("pilut",jac->hypre_type,&flag);CHKERRQ(ierr); 786 if (flag) { 787 ierr = HYPRE_ParCSRPilutCreate(jac->comm_hypre,&jac->hsolver); 788 pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut; 789 pc->ops->view = PCView_HYPRE_Pilut; 790 jac->destroy = HYPRE_ParCSRPilutDestroy; 791 jac->setup = HYPRE_ParCSRPilutSetup; 792 jac->solve = HYPRE_ParCSRPilutSolve; 793 jac->factorrowsize = PETSC_DEFAULT; 794 PetscFunctionReturn(0); 795 } 796 ierr = PetscStrcmp("parasails",jac->hypre_type,&flag);CHKERRQ(ierr); 797 if (flag) { 798 ierr = HYPRE_ParaSailsCreate(jac->comm_hypre,&jac->hsolver); 799 pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails; 800 pc->ops->view = PCView_HYPRE_ParaSails; 801 jac->destroy = HYPRE_ParaSailsDestroy; 802 jac->setup = HYPRE_ParaSailsSetup; 803 jac->solve = HYPRE_ParaSailsSolve; 804 /* initialize */ 805 jac->nlevels = 1; 806 jac->threshhold = .1; 807 jac->filter = .1; 808 jac->loadbal = 0; 809 if (PetscLogPrintInfo) { 810 jac->logging = (int) PETSC_TRUE; 811 } else { 812 jac->logging = (int) PETSC_FALSE; 813 } 814 jac->ruse = (int) PETSC_FALSE; 815 jac->symt = 0; 816 ierr = HYPRE_ParaSailsSetParams(jac->hsolver,jac->threshhold,jac->nlevels);CHKERRQ(ierr); 817 ierr = HYPRE_ParaSailsSetFilter(jac->hsolver,jac->filter);CHKERRQ(ierr); 818 ierr = HYPRE_ParaSailsSetLoadbal(jac->hsolver,jac->loadbal);CHKERRQ(ierr); 819 ierr = HYPRE_ParaSailsSetLogging(jac->hsolver,jac->logging);CHKERRQ(ierr); 820 ierr = HYPRE_ParaSailsSetReuse(jac->hsolver,jac->ruse);CHKERRQ(ierr); 821 ierr = HYPRE_ParaSailsSetSym(jac->hsolver,jac->symt);CHKERRQ(ierr); 822 PetscFunctionReturn(0); 823 } 824 ierr = PetscStrcmp("euclid",jac->hypre_type,&flag);CHKERRQ(ierr); 825 if (flag) { 826 ierr = HYPRE_EuclidCreate(jac->comm_hypre,&jac->hsolver); 827 pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid; 828 pc->ops->view = PCView_HYPRE_Euclid; 829 jac->destroy = HYPRE_EuclidDestroy; 830 jac->setup = HYPRE_EuclidSetup; 831 jac->solve = HYPRE_EuclidSolve; 832 /* initialization */ 833 jac->bjilu = PETSC_FALSE; 834 jac->levels = 1; 835 PetscFunctionReturn(0); 836 } 837 ierr = PetscStrcmp("boomeramg",jac->hypre_type,&flag);CHKERRQ(ierr); 838 if (flag) { 839 ierr = HYPRE_BoomerAMGCreate(&jac->hsolver); 840 pc->ops->setfromoptions = PCSetFromOptions_HYPRE_BoomerAMG; 841 pc->ops->view = PCView_HYPRE_BoomerAMG; 842 pc->ops->applytranspose = PCApplyTranspose_HYPRE_BoomerAMG; 843 pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG; 844 jac->destroy = HYPRE_BoomerAMGDestroy; 845 jac->setup = HYPRE_BoomerAMGSetup; 846 jac->solve = HYPRE_BoomerAMGSolve; 847 jac->applyrichardson = PETSC_FALSE; 848 /* these defaults match the hypre defaults */ 849 jac->cycletype = 1; 850 jac->maxlevels = 25; 851 jac->maxiter = 1; 852 jac->tol = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */ 853 jac->truncfactor = 0.0; 854 jac->strongthreshold = .25; 855 jac->maxrowsum = .9; 856 jac->coarsentype = 6; 857 jac->measuretype = 0; 858 jac->gridsweeps[0] = jac->gridsweeps[1] = jac->gridsweeps[2] = 1; 859 jac->relaxtype[0] = jac->relaxtype[1] = 6; /* Defaults to SYMMETRIC since in PETSc we are using a a PC - most likely with CG */ 860 jac->relaxtype[2] = 9; /*G.E. */ 861 jac->relaxweight = 1.0; 862 jac->outerrelaxweight = 1.0; 863 jac->relaxorder = 1; 864 jac->interptype = 0; 865 jac->agg_nl = 0; 866 jac->pmax = 0; 867 jac->truncfactor = 0.0; 868 jac->agg_num_paths = 1; 869 870 jac->nodal_coarsen = 0; 871 jac->nodal_relax = PETSC_FALSE; 872 jac->nodal_relax_levels = 1; 873 ierr = HYPRE_BoomerAMGSetCycleType(jac->hsolver,jac->cycletype);CHKERRQ(ierr); 874 ierr = HYPRE_BoomerAMGSetMaxLevels(jac->hsolver,jac->maxlevels);CHKERRQ(ierr); 875 ierr = HYPRE_BoomerAMGSetMaxIter(jac->hsolver,jac->maxiter);CHKERRQ(ierr); 876 ierr = HYPRE_BoomerAMGSetTol(jac->hsolver,jac->tol);CHKERRQ(ierr); 877 ierr = HYPRE_BoomerAMGSetTruncFactor(jac->hsolver,jac->truncfactor);CHKERRQ(ierr); 878 ierr = HYPRE_BoomerAMGSetStrongThreshold(jac->hsolver,jac->strongthreshold);CHKERRQ(ierr); 879 ierr = HYPRE_BoomerAMGSetMaxRowSum(jac->hsolver,jac->maxrowsum);CHKERRQ(ierr); 880 ierr = HYPRE_BoomerAMGSetCoarsenType(jac->hsolver,jac->coarsentype);CHKERRQ(ierr); 881 ierr = HYPRE_BoomerAMGSetMeasureType(jac->hsolver,jac->measuretype);CHKERRQ(ierr); 882 ierr = HYPRE_BoomerAMGSetRelaxOrder(jac->hsolver, jac->relaxorder);CHKERRQ(ierr); 883 ierr = HYPRE_BoomerAMGSetInterpType(jac->hsolver,jac->interptype);CHKERRQ(ierr); 884 ierr = HYPRE_BoomerAMGSetAggNumLevels(jac->hsolver,jac->agg_nl); 885 ierr = HYPRE_BoomerAMGSetPMaxElmts(jac->hsolver,jac->pmax);CHKERRQ(ierr); 886 ierr = HYPRE_BoomerAMGSetNumPaths(jac->hsolver,jac->agg_num_paths);CHKERRQ(ierr); 887 ierr = HYPRE_BoomerAMGSetRelaxType(jac->hsolver, jac->relaxtype[0]); /*defaults coarse to 9*/ 888 ierr = HYPRE_BoomerAMGSetNumSweeps(jac->hsolver, jac->gridsweeps[0]); /*defaults coarse to 1 */ 889 PetscFunctionReturn(0); 890 } 891 ierr = PetscStrfree(jac->hypre_type);CHKERRQ(ierr); 892 jac->hypre_type = PETSC_NULL; 893 SETERRQ1(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown HYPRE preconditioner %s; Choices are pilut, parasails, euclid, boomeramg",name); 894 PetscFunctionReturn(0); 895 } 896 EXTERN_C_END 897 898 /* 899 It only gets here if the HYPRE type has not been set before the call to 900 ...SetFromOptions() which actually is most of the time 901 */ 902 #undef __FUNCT__ 903 #define __FUNCT__ "PCSetFromOptions_HYPRE" 904 static PetscErrorCode PCSetFromOptions_HYPRE(PC pc) 905 { 906 PetscErrorCode ierr; 907 int indx; 908 const char *type[] = {"pilut","parasails","boomeramg","euclid"}; 909 PetscTruth flg; 910 911 PetscFunctionBegin; 912 ierr = PetscOptionsHead("HYPRE preconditioner options");CHKERRQ(ierr); 913 ierr = PetscOptionsEList("-pc_hypre_type","HYPRE preconditioner type","PCHYPRESetType",type,4,"boomeramg",&indx,&flg);CHKERRQ(ierr); 914 if (flg) { 915 ierr = PCHYPRESetType_HYPRE(pc,type[indx]);CHKERRQ(ierr); 916 } else { 917 ierr = PCHYPRESetType_HYPRE(pc,"boomeramg");CHKERRQ(ierr); 918 } 919 if (pc->ops->setfromoptions) { 920 ierr = pc->ops->setfromoptions(pc);CHKERRQ(ierr); 921 } 922 ierr = PetscOptionsTail();CHKERRQ(ierr); 923 PetscFunctionReturn(0); 924 } 925 926 #undef __FUNCT__ 927 #define __FUNCT__ "PCHYPRESetType" 928 /*@C 929 PCHYPRESetType - Sets which hypre preconditioner you wish to use 930 931 Input Parameters: 932 + pc - the preconditioner context 933 - name - either pilut, parasails, boomeramg, euclid 934 935 Options Database Keys: 936 -pc_hypre_type - One of pilut, parasails, boomeramg, euclid 937 938 Level: intermediate 939 940 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 941 PCHYPRE 942 943 @*/ 944 PetscErrorCode PETSCKSP_DLLEXPORT PCHYPRESetType(PC pc,const char name[]) 945 { 946 PetscErrorCode ierr,(*f)(PC,const char[]); 947 948 PetscFunctionBegin; 949 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 950 PetscValidCharPointer(name,2); 951 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCHYPRESetType_C",(void (**)(void))&f);CHKERRQ(ierr); 952 if (f) { 953 ierr = (*f)(pc,name);CHKERRQ(ierr); 954 } 955 PetscFunctionReturn(0); 956 } 957 958 #undef __FUNCT__ 959 #define __FUNCT__ "PCHYPREGetType" 960 /*@C 961 PCHYPREGetType - Gets which hypre preconditioner you are using 962 963 Input Parameter: 964 . pc - the preconditioner context 965 966 Output Parameter: 967 . name - either pilut, parasails, boomeramg, euclid 968 969 Level: intermediate 970 971 .seealso: PCCreate(), PCHYPRESetType(), PCType (for list of available types), PC, 972 PCHYPRE 973 974 @*/ 975 PetscErrorCode PETSCKSP_DLLEXPORT PCHYPREGetType(PC pc,const char *name[]) 976 { 977 PetscErrorCode ierr,(*f)(PC,const char*[]); 978 979 PetscFunctionBegin; 980 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 981 PetscValidPointer(name,2); 982 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCHYPREGetType_C",(void (**)(void))&f);CHKERRQ(ierr); 983 if (f) { 984 ierr = (*f)(pc,name);CHKERRQ(ierr); 985 } 986 PetscFunctionReturn(0); 987 } 988 989 /*MC 990 PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre 991 992 Options Database Keys: 993 + -pc_hypre_type - One of pilut, parasails, boomeramg, euclid 994 - Too many others to list, run with -pc_type hypre -pc_hypre_type XXX -help to see options for the XXX 995 preconditioner 996 997 Level: intermediate 998 999 Notes: Apart from pc_hypre_type (for which there is PCHYPRESetType()), 1000 the many hypre options can ONLY be set via the options database (e.g. the command line 1001 or with PetscOptionsSetValue(), there are no functions to set them) 1002 1003 The options -pc_hypre_boomeramg_max_iter and -pc_hypre_boomeramg_rtol refer to the number of iterations 1004 (V-cycles) and tolerance that boomeramg does EACH time it is called. So for example, if 1005 -pc_hypre_boomeramg_max_iter is set to 2 then 2-V-cycles are being used to define the preconditioner 1006 (-pc_hypre_boomeramg_rtol should be set to 0.0 - the default - to strictly use a fixed number of 1007 iterations per hypre call). -ksp_max_it and -ksp_rtol STILL determine the total number of iterations 1008 and tolerance for the Krylov solver. For example, if -pc_hypre_boomeramg_max_iter is 2 and -ksp_max_it is 10 1009 then AT MOST twenty V-cycles of boomeramg will be called. 1010 1011 Note that the option -pc_hypre_boomeramg_relax_type_all defaults to symmetric relaxation 1012 (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry. 1013 Otherwise, you may want to use -pc_hypre_boomeramg_relax_type_all SOR/Jacobi. 1014 If you wish to use BoomerAMG WITHOUT a Krylov method use -ksp_type richardson NOT -ksp_type preonly 1015 and use -ksp_max_it to control the number of V-cycles. 1016 (see the PETSc FAQ.html at the PETSc website under the Documentation tab). 1017 1018 2007-02-03 Using HYPRE-1.11.1b, the routine HYPRE_BoomerAMGSolveT and the option 1019 -pc_hypre_parasails_reuse were failing with SIGSEGV. Dalcin L. 1020 1021 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 1022 PCHYPRESetType() 1023 1024 M*/ 1025 1026 EXTERN_C_BEGIN 1027 #undef __FUNCT__ 1028 #define __FUNCT__ "PCCreate_HYPRE" 1029 PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_HYPRE(PC pc) 1030 { 1031 PC_HYPRE *jac; 1032 PetscErrorCode ierr; 1033 1034 PetscFunctionBegin; 1035 ierr = PetscNewLog(pc,PC_HYPRE,&jac);CHKERRQ(ierr); 1036 pc->data = jac; 1037 pc->ops->destroy = PCDestroy_HYPRE; 1038 pc->ops->setfromoptions = PCSetFromOptions_HYPRE; 1039 pc->ops->setup = PCSetUp_HYPRE; 1040 pc->ops->apply = PCApply_HYPRE; 1041 jac->comm_hypre = MPI_COMM_NULL; 1042 jac->hypre_type = PETSC_NULL; 1043 /* duplicate communicator for hypre */ 1044 ierr = MPI_Comm_dup(((PetscObject)pc)->comm,&(jac->comm_hypre));CHKERRQ(ierr); 1045 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPRESetType_C","PCHYPRESetType_HYPRE",PCHYPRESetType_HYPRE);CHKERRQ(ierr); 1046 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPREGetType_C","PCHYPREGetType_HYPRE",PCHYPREGetType_HYPRE);CHKERRQ(ierr); 1047 PetscFunctionReturn(0); 1048 } 1049 EXTERN_C_END 1050