// ===================================================== void PetscPreconditioner::set_petsc_preconditioner_type (const PreconditionerType & preconditioner_type, PC & pc, const int ¶llelOverlapping) { int ierr = 0; switch(preconditioner_type) { case IDENTITY_PRECOND: ierr = PCSetType(pc, (char*) PCNONE); CHKERRABORT(MPI_COMM_WORLD, ierr); break; case CHOLESKY_PRECOND: ierr = PCSetType(pc, (char*) PCCHOLESKY); CHKERRABORT(MPI_COMM_WORLD, ierr); break; case ICC_PRECOND: ierr = PCSetType(pc, (char*) PCICC); CHKERRABORT(MPI_COMM_WORLD, ierr); break; case ILU_PRECOND: { int nprocs; MPI_Comm_size(MPI_COMM_WORLD, &nprocs); //TODO // In serial, just set the ILU preconditioner type if(nprocs == 1) { ierr = PCSetType(pc, (char*) PCILU); CHKERRABORT(MPI_COMM_WORLD, ierr); } else { // But PETSc has no truly parallel ILU, instead you have to set // an actual parallel preconditioner (e.g. block Jacobi (parlleloverlapping 0) or ASM (parlleloverlapping >0)) // and then assign ILU sub-preconditioners. set_petsc_preconditioner_type(ASM_PRECOND, pc); PCASMSetOverlap(pc, parallelOverlapping); PCSetUp(pc); // Set ILU as the sub preconditioner type set_petsc_subpreconditioner_type(PCILU, pc); } break; } case LU_PRECOND: { int nprocs; MPI_Comm_size(MPI_COMM_WORLD, &nprocs); if(nprocs == 1) { ierr = PCSetType(pc, (char*) PCLU); CHKERRABORT(MPI_COMM_WORLD, ierr); } else { ierr = PCSetType(pc, (char*) PCLU); CHKERRABORT(MPI_COMM_WORLD, ierr); ierr = PCFactorSetMatSolverPackage(pc, MATSOLVERMUMPS); CHKERRABORT(MPI_COMM_WORLD, ierr); ierr = PCFactorSetUpMatSolverPackage(pc); CHKERRABORT(MPI_COMM_WORLD, ierr); Mat F; ierr = PCFactorGetMatrix(pc, &F); CHKERRABORT(MPI_COMM_WORLD, ierr); ierr = MatMumpsSetIcntl(F, 14, 30); CHKERRABORT(MPI_COMM_WORLD, ierr); } break; } case SLU_PRECOND: ierr = PCSetType(pc, (char*) PCLU); CHKERRABORT(MPI_COMM_WORLD, ierr); ierr = PCFactorSetMatSolverPackage(pc, MATSOLVERSUPERLU_DIST); CHKERRABORT(MPI_COMM_WORLD, ierr); break; //here we set the SuperLU_dist solver package case MLU_PRECOND: //here we set the MUMPS parallel direct solver package ierr = PCSetType(pc, (char*) PCLU); CHKERRABORT(MPI_COMM_WORLD, ierr); ierr = PCFactorSetMatSolverPackage(pc, MATSOLVERMUMPS); CHKERRABORT(MPI_COMM_WORLD, ierr); ierr = PCFactorSetUpMatSolverPackage(pc); CHKERRABORT(MPI_COMM_WORLD, ierr); Mat F; ierr = PCFactorGetMatrix(pc, &F); CHKERRABORT(MPI_COMM_WORLD, ierr); ierr = MatMumpsSetIcntl(F, 14, 30); CHKERRABORT(MPI_COMM_WORLD, ierr); break; case ULU_PRECOND: //here we set the Umfpack serial direct solver package ierr = PCSetType(pc, (char*) PCLU); CHKERRABORT(MPI_COMM_WORLD, ierr); ierr = PCFactorSetMatSolverPackage(pc, MATSOLVERUMFPACK); CHKERRABORT(MPI_COMM_WORLD, ierr); ierr = PCFactorSetUpMatSolverPackage(pc); CHKERRABORT(MPI_COMM_WORLD, ierr); break; case MCC_PRECOND: ierr = PCSetType(pc, (char*) PCCHOLESKY); CHKERRABORT(MPI_COMM_WORLD, ierr); ierr = PCFactorSetMatSolverPackage(pc, MATSOLVERMUMPS); CHKERRABORT(MPI_COMM_WORLD, ierr); //here we set the MUMPS parallel direct solver package break; case ASM_PRECOND: ierr = PCSetType(pc, (char*) PCASM); CHKERRABORT(MPI_COMM_WORLD, ierr); break; case FIELDSPLIT_PRECOND: ierr = PCSetType(pc, (char*) PCFIELDSPLIT); CHKERRABORT(MPI_COMM_WORLD, ierr); break; case JACOBI_PRECOND: ierr = PCSetType(pc, (char*) PCJACOBI); CHKERRABORT(MPI_COMM_WORLD, ierr); break; case BLOCK_JACOBI_PRECOND: ierr = PCSetType(pc, (char*) PCBJACOBI); CHKERRABORT(MPI_COMM_WORLD, ierr); break; case SOR_PRECOND: ierr = PCSetType(pc, (char*) PCSOR); CHKERRABORT(MPI_COMM_WORLD, ierr); break; case EISENSTAT_PRECOND: ierr = PCSetType(pc, (char*) PCEISENSTAT); CHKERRABORT(MPI_COMM_WORLD, ierr); break; case AMG_PRECOND: ierr = PCSetType(pc, (char*) PCHYPRE); CHKERRABORT(MPI_COMM_WORLD, ierr); break; case MG_PRECOND: ierr = PCSetType(pc, (char*) PCMG); CHKERRABORT(MPI_COMM_WORLD, ierr); break; case LSC_PRECOND: ierr = PCSetType(pc, (char*) PCLSC); CHKERRABORT(MPI_COMM_WORLD, 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(MPI_COMM_WORLD, ierr); break; #endif case SHELL_PRECOND: ierr = PCSetType(pc, (char*) PCSHELL); CHKERRABORT(MPI_COMM_WORLD, ierr); break; default: std::cerr << "ERROR: Unsupported PETSC Preconditioner: " << preconditioner_type << std::endl << "Continuing with PETSC defaults" << std::endl; } //Let the commandline override stuff if(preconditioner_type != AMG_PRECOND && preconditioner_type != MG_PRECOND) PCSetFromOptions(pc); //!!!!!! }
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); } }