void PetscPreconditioner<T>::init () { if(!this->_matrix) { libMesh::err << "ERROR: No matrix set for PetscPreconditioner, but init() called" << std::endl; libmesh_error(); } // Clear the preconditioner in case it has been created in the past if (!this->_is_initialized) { // Should probably use PCReset(), but it's not working at the moment so we'll destroy instead if (_pc) { int ierr = LibMeshPCDestroy(&_pc); LIBMESH_CHKERRABORT(ierr); } int ierr = PCCreate(this->comm().get(),&_pc); LIBMESH_CHKERRABORT(ierr); PetscMatrix<T> * pmatrix = libmesh_cast_ptr<PetscMatrix<T>*, SparseMatrix<T> >(this->_matrix); _mat = pmatrix->mat(); } int ierr = PCSetOperators(_pc,_mat,_mat,SAME_NONZERO_PATTERN); LIBMESH_CHKERRABORT(ierr); // Set the PCType. Note: this used to be done *before* the call to // PCSetOperators(), and only when !_is_initialized, but // 1.) Some preconditioners (those employing sub-preconditioners, // for example) have to call PCSetUp(), and can only do this after // the operators have been set. // 2.) It should be safe to call set_petsc_preconditioner_type() // multiple times. set_petsc_preconditioner_type(this->_preconditioner_type, _pc); this->_is_initialized = true; }
// ================================================= void PetscPreconditioner::init() { if(!this->_matrix) { std::cerr << "ERROR: No matrix set for PetscPreconditioner, but init() called" << std::endl; abort(); } //Clear the preconditioner in case it has been created in the past if(!this->_is_initialized) { //Create the preconditioning object PCCreate(MPI_COMM_WORLD, &_pc); //Set the PCType set_petsc_preconditioner_type(this->_preconditioner_type, _pc); // #ifdef LIBMESH_HAVE_PETSC_HYPRE // if(this->_preconditioner_type == AMG_PRECOND) // PCHYPRESetType(this->_pc, "boomerang"); // #endif PetscMatrix * pmatrix = libmeshM_cast_ptr<PetscMatrix*, SparseMatrix >(this->_matrix); _mat = pmatrix->mat(); } //PCSetOperators(_pc,_mat,_mat,SAME_NONZERO_PATTERN); PCSetOperators(_pc, _mat, _mat); //PETSC3p5 this->_is_initialized = true; }
// ===================================================== 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); //!!!!!! }