#if defined(PETSC_HAVE_FORTRAN_CAPS) #define pchypresettype_ PCHYPRESETTYPE #define pchypregettype_ PCHYPREGETTYPE #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) #define pchypresettype_ pchypresettype #define pchypregettype_ pchypregettype #endif EXTERN_C_BEGIN void PETSC_STDCALL pchypresettype_(PC *pc, CHAR name PETSC_MIXED_LEN(len),PetscErrorCode *ierr PETSC_END_LEN(len) ) { char *t; FIXCHAR(name,len,t); *ierr = PCHYPRESetType(*pc,t); FREECHAR(name,t); } void PETSC_STDCALL pchypregettype_(PC *pc,CHAR name PETSC_MIXED_LEN(len),PetscErrorCode *ierr PETSC_END_LEN(len)) { const char *tname; *ierr = PCHYPREGetType(*pc,&tname); *ierr = PetscStrncpy(name,tname,len);if (*ierr) return; FIXRETURNCHAR(PETSC_TRUE,name,len); } EXTERN_C_END
/*! \brief solve simple use a Krylov solver + Simple selected Parallel Pre-conditioner * */ void solve_Krylov_simple(Mat & A_, const Vec & b_, Vec & x_) { PETSC_SAFE_CALL(KSPSetType(ksp,s_type)); // We set the size of x according to the Matrix A PetscInt row; PetscInt col; PetscInt row_loc; PetscInt col_loc; PETSC_SAFE_CALL(MatGetSize(A_,&row,&col)); PETSC_SAFE_CALL(MatGetLocalSize(A_,&row_loc,&col_loc)); PC pc; // We set the Matrix operators PETSC_SAFE_CALL(KSPSetOperators(ksp,A_,A_)); // We set the pre-conditioner PETSC_SAFE_CALL(KSPGetPC(ksp,&pc)); // PETSC_SAFE_CALL(PCSetType(pc,PCJACOBI)); PETSC_SAFE_CALL(PCSetType(pc,PCHYPRE)); // PCGAMGSetNSmooths(pc,0); PCFactorSetShiftType(pc, MAT_SHIFT_NONZERO); PCFactorSetShiftAmount(pc, PETSC_DECIDE); PCHYPRESetType(pc, "boomeramg"); MatSetBlockSize(A_,4); PetscOptionsSetValue("-pc_hypre_boomeramg_print_statistics","2"); PetscOptionsSetValue("-pc_hypre_boomeramg_max_iter","1000"); PetscOptionsSetValue("-pc_hypre_boomeramg_nodal_coarsen","true"); PetscOptionsSetValue("-pc_hypre_boomeramg_relax_type_all","SOR/Jacobi"); PetscOptionsSetValue("-pc_hypre_boomeramg_coarsen_type","Falgout"); PetscOptionsSetValue("-pc_hypre_boomeramg_cycle_type","W"); PetscOptionsSetValue("-pc_hypre_boomeramg_max_levels","10"); KSPSetFromOptions(ksp); // if we are on on best solve set-up a monitor function if (try_solve == true) { // for bench-mark we are interested in non-preconditioned norm PETSC_SAFE_CALL(KSPMonitorSet(ksp,monitor,&vres,NULL)); // Disable convergence check PETSC_SAFE_CALL(KSPSetConvergenceTest(ksp,KSPConvergedSkip,NULL,NULL)); } // Solve the system PETSC_SAFE_CALL(KSPSolve(ksp,b_,x_)); auto & v_cl = create_vcluster(); // if (try_solve == true) // { // calculate error statistic about the solution solError err = statSolutionError(A_,b_,x_); if (v_cl.getProcessUnitID() == 0) { std::cout << "Method: " << s_type << " " << " pre-conditoner: " << PCJACOBI << " iterations: " << err.its << std::endl; std::cout << "Norm of error: " << err.err_norm << " Norm infinity: " << err.err_inf << std::endl; } // } }
void PetscPreconditioner<T>::set_petsc_preconditioner_type (const PreconditionerType & preconditioner_type, PC & pc) { int ierr = 0; // get the communicator from the PETSc object Parallel::communicator comm; PetscObjectGetComm((PetscObject)pc, &comm); Parallel::Communicator communicator(comm); switch (preconditioner_type) { case IDENTITY_PRECOND: ierr = PCSetType (pc, (char*) PCNONE); CHKERRABORT(comm,ierr); break; case CHOLESKY_PRECOND: ierr = PCSetType (pc, (char*) PCCHOLESKY); CHKERRABORT(comm,ierr); break; case ICC_PRECOND: ierr = PCSetType (pc, (char*) PCICC); CHKERRABORT(comm,ierr); break; case ILU_PRECOND: { // In serial, just set the ILU preconditioner type if (communicator.size()) { ierr = PCSetType (pc, (char*) PCILU); CHKERRABORT(comm,ierr); } else { // But PETSc has no truly parallel ILU, instead you have to set // an actual parallel preconditioner (e.g. block Jacobi) and then // assign ILU sub-preconditioners. ierr = PCSetType (pc, (char*) PCBJACOBI); CHKERRABORT(comm,ierr); // Set ILU as the sub preconditioner type set_petsc_subpreconditioner_type(PCILU, pc); } break; } case LU_PRECOND: { // In serial, just set the LU preconditioner type if (communicator.size()) { ierr = PCSetType (pc, (char*) PCLU); CHKERRABORT(comm,ierr); } else { // But PETSc has no truly parallel LU, instead you have to set // an actual parallel preconditioner (e.g. block Jacobi) and then // assign LU sub-preconditioners. ierr = PCSetType (pc, (char*) PCBJACOBI); CHKERRABORT(comm,ierr); // Set ILU as the sub preconditioner type set_petsc_subpreconditioner_type(PCLU, pc); } break; } case ASM_PRECOND: { // In parallel, I think ASM uses ILU by default as the sub-preconditioner... // I tried setting a different sub-preconditioner here, but apparently the matrix // is not in the correct state (at this point) to call PCSetUp(). ierr = PCSetType (pc, (char*) PCASM); CHKERRABORT(comm,ierr); break; } case JACOBI_PRECOND: ierr = PCSetType (pc, (char*) PCJACOBI); CHKERRABORT(comm,ierr); break; case BLOCK_JACOBI_PRECOND: ierr = PCSetType (pc, (char*) PCBJACOBI); CHKERRABORT(comm,ierr); break; case SOR_PRECOND: ierr = PCSetType (pc, (char*) PCSOR); CHKERRABORT(comm,ierr); break; case EISENSTAT_PRECOND: ierr = PCSetType (pc, (char*) PCEISENSTAT); CHKERRABORT(comm,ierr); break; case AMG_PRECOND: ierr = PCSetType (pc, (char*) PCHYPRE); CHKERRABORT(comm,ierr); break; #if !(PETSC_VERSION_LESS_THAN(2,1,2)) // Only available for PETSC >= 2.1.2 case USER_PRECOND: ierr = PCSetType (pc, (char*) PCMAT); CHKERRABORT(comm,ierr); break; #endif case SHELL_PRECOND: ierr = PCSetType (pc, (char*) PCSHELL); CHKERRABORT(comm,ierr); break; default: libMesh::err << "ERROR: Unsupported PETSC Preconditioner: " << preconditioner_type << std::endl << "Continuing with PETSC defaults" << std::endl; } // Set additional options if we are doing AMG and // HYPRE is available #ifdef LIBMESH_HAVE_PETSC_HYPRE if (preconditioner_type == AMG_PRECOND) { ierr = PCHYPRESetType(pc, "boomeramg"); CHKERRABORT(comm,ierr); } #endif // Let the commandline override stuff // FIXME: Unless we are doing AMG??? if (preconditioner_type != AMG_PRECOND) { ierr = PCSetFromOptions(pc); CHKERRABORT(comm,ierr); } }
std::pair<std::string,std::string> RBConstructionBase<Base>::set_alternative_solver (AutoPtr<LinearSolver<Number> >& #ifdef LIBMESH_HAVE_PETSC ls #endif ) { // It seems that setting it this generic way has no effect... // PreconditionerType orig_pc = this->linear_solver->preconditioner_type(); // this->linear_solver->set_preconditioner_type(AMG_PRECOND); // so we do it the "hard" way. std::string orig_petsc_pc_type_string, orig_petsc_ksp_type_string; #ifdef LIBMESH_HAVE_PETSC // ... but we can set it the "hard" way PetscLinearSolver<Number>* petsc_linear_solver = libmesh_cast_ptr<PetscLinearSolver<Number>*>(ls.get()); // Note: #define PCType char*, and PCGetType just sets a pointer. We'll use // the string below to make a real copy, and set the PC back to its original // type at the end of the function. #if PETSC_VERSION_LESS_THAN(3,0,0) || !PETSC_VERSION_LESS_THAN(3,4,0) // Pre-3.0 and petsc-dev (as of October 2012) use non-const versions PCType orig_petsc_pc_type; KSPType orig_petsc_ksp_type; #else const PCType orig_petsc_pc_type; const KSPType orig_petsc_ksp_type; #endif if (petsc_linear_solver) { PC pc = petsc_linear_solver->pc(); int ierr = PCGetType(pc, &orig_petsc_pc_type); LIBMESH_CHKERRABORT(ierr); KSP ksp = petsc_linear_solver->ksp(); ierr = KSPGetType(ksp, &orig_petsc_ksp_type); LIBMESH_CHKERRABORT(ierr); // libMesh::out << "orig_petsc_pc_type (before)=" << orig_petsc_pc_type << std::endl; // Make actual copies of the original PC and KSP types orig_petsc_pc_type_string = orig_petsc_pc_type; orig_petsc_ksp_type_string = orig_petsc_ksp_type; #ifdef LIBMESH_HAVE_PETSC_HYPRE // Set solver/PC combo specified in input file... if (this->alternative_solver == "amg") { // Set HYPRE and boomeramg PC types ierr = PCSetType(pc, PCHYPRE); LIBMESH_CHKERRABORT(ierr); ierr = PCHYPRESetType(pc, "boomeramg"); LIBMESH_CHKERRABORT(ierr); } #endif // LIBMESH_HAVE_PETSC_HYPRE if (this->alternative_solver == "mumps") { // We'll use MUMPS... TODO: configure libmesh to detect // when MUMPS is available via PETSc. // No initial guesses can be specified with KSPPREONLY. We // can leave the solver as gmres or whatever and it should // converge in 1 iteration. Otherwise, to use KSPPREONLY, // you may need to do: // KSPSetInitialGuessNonzero(ksp, PETSC_FALSE); // ierr = KSPSetType(ksp, KSPPREONLY); // LIBMESH_CHKERRABORT(ierr); // Need to call the equivalent for the command line options: // -ksp_type preonly -pc_type lu -pc_factor_mat_solver_package mumps ierr = PCSetType(pc, PCLU); LIBMESH_CHKERRABORT(ierr); #if !(PETSC_VERSION_LESS_THAN(3,0,0)) ierr = PCFactorSetMatSolverPackage(pc,"mumps"); LIBMESH_CHKERRABORT(ierr); #endif } } else { // Otherwise, the cast failed and we are not using PETSc... libMesh::out << "You are not using PETSc, so don't know how to set AMG PC." << std::endl; libMesh::out << "Returning empty string!" << std::endl; } #endif // LIBMESH_HAVE_PETSC return std::make_pair(orig_petsc_pc_type_string, orig_petsc_ksp_type_string); }
/* This function returns the suitable solver for pressure. linear system */ KSP Solver_get_pressure_solver(Mat lhs, Parameters *params) { KSP solver; PC pc; double rtol; int ierr; PetscLogDouble T1, T2; rtol = params->resmax; ierr = KSPCreate(PETSC_COMM_WORLD, &solver); PETScErrAct(ierr); short int hasnullspace = NO; if (hasnullspace) { MatNullSpace nullsp; MatNullSpaceCreate(PETSC_COMM_WORLD, PETSC_TRUE, 0, PETSC_NULL, &nullsp); KSPSetNullSpace(solver, nullsp); //MatNullSpaceDestroy(nullsp); } ierr = KSPSetOperators(solver, lhs, lhs, SAME_PRECONDITIONER); PETScErrAct(ierr); ierr = KSPSetType(solver, KSPGMRES); PETScErrAct(ierr); ierr = KSPGMRESSetRestart(solver, 20); PETScErrAct(ierr); ierr = KSPSetTolerances(solver, rtol, PETSC_DEFAULT, PETSC_DEFAULT, 300); PETScErrAct(ierr); ierr = KSPGetPC(solver, &pc); PETScErrAct(ierr); //PCSetType(pc, PCNONE); //PCSetType(pc, PCASM); PCSetType(pc, PCHYPRE); PCHYPRESetType(pc,"boomeramg"); ierr = PetscOptionsSetValue("-pc_hypre_boomeramg_max_levels", "25"); PETScErrAct(ierr); ierr = PetscOptionsSetValue("-pc_hypre_boomeramg_strong_threshold", "0.0"); PETScErrAct(ierr); ierr = PetscOptionsSetValue("-pc_hypre_boomeramg_relax_type_all", "SOR/Jacobi"); PETScErrAct(ierr); //ierr = PetscOptionsSetValue("-pc_hypre_boomeramg_cycle_type", ""); PETScErrAct(ierr); //ierr = PetscOptionsSetValue("-pc_hypre_boomeramg_cycle_type", "V"); PETScErrAct(ierr); //ierr = PetscOptionsSetValue("-pc_hypre_boomeramg_coarsen_type", "PMIS"); PETScErrAct(ierr); //ierr = PetscOptionsSetValue("-pc_hypre_boomeramg_truncfactor", "0.9"); PETScErrAct(ierr); /*******************************************************************************************************/ /*******************************************************************************************************/ /*******************************************************************************************************/ /* Hypre-Petsc Interface. The most important parameters to be set are 1- Strong Threshold 2- Truncation Factor 3- Coarsennig Type */ /* Between 0 to 1 */ /* "0 "gives better convergence rate (in 3D). */ /* Suggested values (By Hypre manual): 0.25 for 2D, 0.5 for 3D ierr = PetscOptionsSetValue("-pc_hypre_boomeramg_strong_threshold", "0.0"); PETScErrAct(ierr); */ /*******************************************************************************************************/ /* Available Options: "CLJP","Ruge-Stueben","modifiedRuge-Stueben","Falgout", "PMIS", "HMIS" Falgout is usually the best. ierr = PetscOptionsSetValue("-pc_hypre_boomeramg_coarsen_type", "Falgout"); PETScErrAct(ierr); */ /*******************************************************************************************************/ /* Availble options: "local", "global" ierr = PetscOptionsSetValue("-pc_hypre_boomeramg_measure_type", "local"); PETScErrAct(ierr); */ /*******************************************************************************************************/ /* Availble options: Jacobi,sequential-Gauss-Seidel, SOR/Jacobi,backward-SOR/Jacobi,symmetric-SOR/Jacobi,Gaussian-elimination Important: If you are using a symmetric KSP solver (like CG), you should use a symmetric smoother here. ierr = PetscOptionsSetValue("-pc_hypre_boomeramg_relax_type_all", "symmetric-SOR/Jacobi"); PETScErrAct(ierr); */ /*******************************************************************************************************/ /* Available options: "V", "W" ierr = PetscOptionsSetValue("-pc_hypre_boomeramg_cycle_type", "V"); PETScErrAct(ierr); */ /*******************************************************************************************************/ /* Availble options: "classical", "", "", "direct", "multipass", "multipass-wts", "ext+i", "ext+i-cc", "standard", "standard-wts", "", "", "FF", "FF1" ierr = PetscOptionsSetValue("-pc_hypre_boomeramg_interp_type", ""); PETScErrAct(ierr); */ /*******************************************************************************************************/ /* Available options: Greater than zero. Use zero for the best convergence. However, if you have memory problems, use greate than zero to save some memory. ierr = PetscOptionsSetValue("-pc_hypre_boomeramg_truncfactor", "0.0"); PETScErrAct(ierr); */ /* Preconditioner Generation Options PCSetType(pc,PCHYPRE) or -pc_type hypre -pc_hypre_boomeramg_max_levels nmax -pc_hypre_boomeramg_truncfactor -pc_hypre_boomeramg_strong_threshold -pc_hypre_boomeramg_max_row_sum -pc_hypre_boomeramg_no_CF -pc_hypre_boomeramg_coarsen_type CLJP,Ruge-Stueben,modifiedRuge-Stueben, -pc_hypre_boomeramg_measure_type local,global Preconditioner Iteration Options -pc_hypre_boomeramg_relax_type_all Jacobi,sequential-Gauss-Seidel, SOR/Jacobi,backward-SOR/Jacobi,symmetric-SOR/Jacobi,Gaussian-eliminat -pc_hypre_boomeramg_relax_type_fine -pc_hypre_boomeramg_relax_type_down -pc_hypre_boomeramg_relax_type_up -pc_hypre_boomeramg_relax_weight_all r -pc_hypre_boomeramg_outer_relax_weight_all r -pc_hypre_boomeramg_grid_sweeps_down n -pc_hypre_boomeramg_grid_sweeps_up n -pc_hypre_boomeramg_grid_sweeps_coarse n -pc_hypre_boomeramg_tol tol -pc_hypre_boomeramg_max_iter it */ /* //ierr = PCSetType(pc, PCASM); PETScErrAct(ierr); ierr = PCSetType(pc, PCNONE); PETScErrAct(ierr); //ierr = PCSetType(pc, PCILU); PETScErrAct(ierr); //ierr = PCSetType(pc, PCBJACOBI); PETScErrAct(ierr); //ierr = PCSetType(pc, PCLU); PETScErrAct(ierr); //ierr = PCSetType(pc, PCEISENSTAT); PETScErrAct(ierr); //ierr = PCSetType(pc, PCSOR); PETScErrAct(ierr); //ierr = PCSetType(pc, PCJACOBI); PETScErrAct(ierr); //ierr = PCSetType(pc, PCNONE); PETScErrAct(ierr); */ /* ierr = KSPGetPC(solver, &pc); PETScErrAct(ierr); ierr = PCSetType(pc, PCILU); PETScErrAct(ierr); ierr = PCFactorSetLevels(pc, 3); PETScErrAct(ierr); //ierr = PCFactorSetUseDropTolerance(pc, 1e-3, .1, 50); PETScErrAct(ierr); //ierr = PCFactorSetFill(pc, 30.7648); PETScErrAct(ierr); ierr = PCFactorSetReuseOrdering(pc, PETSC_TRUE); PETScErrAct(ierr); ierr = PCFactorSetReuseFill(pc, PETSC_TRUE); PETScErrAct(ierr); ierr = PCFactorSetAllowDiagonalFill(pc); PETScErrAct(ierr); //ierr = PCFactorSetUseInPlace(pc); PETScErrAct(ierr); */ ierr = KSPSetInitialGuessNonzero(solver, PETSC_TRUE); PETScErrAct(ierr); ierr = PetscGetTime(&T1);PETScErrAct(ierr); ierr = KSPSetFromOptions(solver); PETScErrAct(ierr); ierr = PetscGetTime(&T2);PETScErrAct(ierr); PetscPrintf(PCW, "Setup time for the Pressure solver was:%f\n", (T2 - T1)); ierr = KSPView(solver, PETSC_VIEWER_STDOUT_WORLD); PETScErrAct(ierr); return solver; }