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,"pilut");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 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 907 PetscErrorCode ierr; 908 int indx; 909 const char *type[] = {"pilut","parasails","boomeramg","euclid"}; 910 PetscTruth flg; 911 912 PetscFunctionBegin; 913 ierr = PetscOptionsHead("HYPRE preconditioner options");CHKERRQ(ierr); 914 ierr = PetscOptionsEList("-pc_hypre_type","HYPRE preconditioner type","PCHYPRESetType",type,4,"pilut",&indx,&flg);CHKERRQ(ierr); 915 if (PetscOptionsPublishCount) { /* force the default if it was not yet set and user did not set with option */ 916 if (!flg && !jac->hypre_type) { 917 flg = PETSC_TRUE; 918 indx = 0; 919 } 920 } 921 if (flg) { 922 ierr = PCHYPRESetType_HYPRE(pc,type[indx]);CHKERRQ(ierr); 923 } 924 if (pc->ops->setfromoptions) { 925 ierr = pc->ops->setfromoptions(pc);CHKERRQ(ierr); 926 } 927 ierr = PetscOptionsTail();CHKERRQ(ierr); 928 PetscFunctionReturn(0); 929 } 930 931 #undef __FUNCT__ 932 #define __FUNCT__ "PCHYPRESetType" 933 /*@C 934 PCHYPRESetType - Sets which hypre preconditioner you wish to use 935 936 Input Parameters: 937 + pc - the preconditioner context 938 - name - either pilut, parasails, boomeramg, euclid 939 940 Options Database Keys: 941 -pc_hypre_type - One of pilut, parasails, boomeramg, euclid 942 943 Level: intermediate 944 945 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 946 PCHYPRE 947 948 @*/ 949 PetscErrorCode PETSCKSP_DLLEXPORT PCHYPRESetType(PC pc,const char name[]) 950 { 951 PetscErrorCode ierr,(*f)(PC,const char[]); 952 953 PetscFunctionBegin; 954 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 955 PetscValidCharPointer(name,2); 956 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCHYPRESetType_C",(void (**)(void))&f);CHKERRQ(ierr); 957 if (f) { 958 ierr = (*f)(pc,name);CHKERRQ(ierr); 959 } 960 PetscFunctionReturn(0); 961 } 962 963 #undef __FUNCT__ 964 #define __FUNCT__ "PCHYPREGetType" 965 /*@C 966 PCHYPREGetType - Gets which hypre preconditioner you are using 967 968 Input Parameter: 969 . pc - the preconditioner context 970 971 Output Parameter: 972 . name - either pilut, parasails, boomeramg, euclid 973 974 Level: intermediate 975 976 .seealso: PCCreate(), PCHYPRESetType(), PCType (for list of available types), PC, 977 PCHYPRE 978 979 @*/ 980 PetscErrorCode PETSCKSP_DLLEXPORT PCHYPREGetType(PC pc,const char *name[]) 981 { 982 PetscErrorCode ierr,(*f)(PC,const char*[]); 983 984 PetscFunctionBegin; 985 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 986 PetscValidPointer(name,2); 987 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCHYPREGetType_C",(void (**)(void))&f);CHKERRQ(ierr); 988 if (f) { 989 ierr = (*f)(pc,name);CHKERRQ(ierr); 990 } 991 PetscFunctionReturn(0); 992 } 993 994 /*MC 995 PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre 996 997 Options Database Keys: 998 + -pc_hypre_type - One of pilut, parasails, boomeramg, euclid 999 - Too many others to list, run with -pc_type hypre -pc_hypre_type XXX -help to see options for the XXX 1000 preconditioner 1001 1002 Level: intermediate 1003 1004 Notes: Apart from pc_hypre_type (for which there is PCHYPRESetType()), 1005 the many hypre options can ONLY be set via the options database (e.g. the command line 1006 or with PetscOptionsSetValue(), there are no functions to set them) 1007 1008 The options -pc_hypre_boomeramg_max_iter and -pc_hypre_boomeramg_rtol refer to the number of iterations 1009 (V-cycles) and tolerance that boomeramg does EACH time it is called. So for example, if 1010 -pc_hypre_boomeramg_max_iter is set to 2 then 2-V-cycles are being used to define the preconditioner 1011 (-pc_hypre_boomeramg_rtol should be set to 0.0 - the default - to strictly use a fixed number of 1012 iterations per hypre call). -ksp_max_it and -ksp_rtol STILL determine the total number of iterations 1013 and tolerance for the Krylov solver. For example, if -pc_hypre_boomeramg_max_iter is 2 and -ksp_max_it is 10 1014 then AT MOST twenty V-cycles of boomeramg will be called. 1015 1016 Note that the option -pc_hypre_boomeramg_relax_type_all defaults to symmetric relaxation 1017 (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry. 1018 Otherwise, you may want to use -pc_hypre_boomeramg_relax_type_all SOR/Jacobi. 1019 If you wish to use BoomerAMG WITHOUT a Krylov method use -ksp_type richardson NOT -ksp_type preonly 1020 and use -ksp_max_it to control the number of V-cycles. 1021 (see the PETSc FAQ.html at the PETSc website under the Documentation tab). 1022 1023 2007-02-03 Using HYPRE-1.11.1b, the routine HYPRE_BoomerAMGSolveT and the option 1024 -pc_hypre_parasails_reuse were failing with SIGSEGV. Dalcin L. 1025 1026 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 1027 PCHYPRESetType() 1028 1029 M*/ 1030 1031 EXTERN_C_BEGIN 1032 #undef __FUNCT__ 1033 #define __FUNCT__ "PCCreate_HYPRE" 1034 PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_HYPRE(PC pc) 1035 { 1036 PC_HYPRE *jac; 1037 PetscErrorCode ierr; 1038 1039 PetscFunctionBegin; 1040 ierr = PetscNewLog(pc,PC_HYPRE,&jac);CHKERRQ(ierr); 1041 pc->data = jac; 1042 pc->ops->destroy = PCDestroy_HYPRE; 1043 pc->ops->setfromoptions = PCSetFromOptions_HYPRE; 1044 pc->ops->setup = PCSetUp_HYPRE; 1045 pc->ops->apply = PCApply_HYPRE; 1046 jac->comm_hypre = MPI_COMM_NULL; 1047 jac->hypre_type = PETSC_NULL; 1048 /* duplicate communicator for hypre */ 1049 ierr = MPI_Comm_dup(((PetscObject)pc)->comm,&(jac->comm_hypre));CHKERRQ(ierr); 1050 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPRESetType_C","PCHYPRESetType_HYPRE",PCHYPRESetType_HYPRE);CHKERRQ(ierr); 1051 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPREGetType_C","PCHYPREGetType_HYPRE",PCHYPREGetType_HYPRE);CHKERRQ(ierr); 1052 PetscFunctionReturn(0); 1053 } 1054 EXTERN_C_END 1055