virtual void setupInternal(NumericVector<Number> &X) { PetscVector<Number> *pX = cast_ptr<PetscVector<Number> *>(&X); PetscErrorCode ierr; ierr = TSSetIFunction(this->_ts,PETSC_NULL,this->_computeIFunction,this); CHKERRABORT(libMesh::COMM_WORLD,ierr); PetscMatrix<Number> *mat = cast_ptr<PetscMatrix<Number> *>(this->_fe_problem.getNonlinearSystem().sys().matrix); Mat pmat = mat->mat(); ierr = TSSetIJacobian(this->_ts,pmat,pmat,this->_computeIJacobian,this); CHKERRABORT(libMesh::COMM_WORLD,ierr); ierr = TSSetFromOptions(this->_ts); CHKERRABORT(libMesh::COMM_WORLD,ierr); ierr = TSSetSolution(_ts,pX->vec()); CHKERRABORT(libMesh::COMM_WORLD,ierr); }
// ================================================= 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 PetscMatrix<T>::add (const T a_in, SparseMatrix<T> &X_in) { libmesh_assert (this->initialized()); // sanity check. but this cannot avoid // crash due to incompatible sparsity structure... libmesh_assert_equal_to (this->m(), X_in.m()); libmesh_assert_equal_to (this->n(), X_in.n()); PetscScalar a = static_cast<PetscScalar> (a_in); PetscMatrix<T>* X = libmesh_cast_ptr<PetscMatrix<T>*> (&X_in); libmesh_assert (X); PetscErrorCode ierr=0; // the matrix from which we copy the values has to be assembled/closed // X->close (); libmesh_assert(X->closed()); semiparallel_only(); // 2.2.x & earlier style #if PETSC_VERSION_LESS_THAN(2,3,0) ierr = MatAXPY(&a, X->_mat, _mat, SAME_NONZERO_PATTERN); LIBMESH_CHKERRABORT(ierr); // 2.3.x & newer #else ierr = MatAXPY(_mat, a, X->_mat, DIFFERENT_NONZERO_PATTERN); LIBMESH_CHKERRABORT(ierr); #endif }
std::pair<unsigned int, Real> PetscNonlinearSolver<T>::solve (SparseMatrix<T>& jac_in, // System Jacobian Matrix NumericVector<T>& x_in, // Solution vector NumericVector<T>& r_in, // Residual vector const double, // Stopping tolerance const unsigned int) { START_LOG("solve()", "PetscNonlinearSolver"); this->init (); // Make sure the data passed in are really of Petsc types PetscMatrix<T>* jac = libmesh_cast_ptr<PetscMatrix<T>*>(&jac_in); PetscVector<T>* x = libmesh_cast_ptr<PetscVector<T>*>(&x_in); PetscVector<T>* r = libmesh_cast_ptr<PetscVector<T>*>(&r_in); PetscErrorCode ierr=0; PetscInt n_iterations =0; // Should actually be a PetscReal, but I don't know which version of PETSc first introduced PetscReal Real final_residual_norm=0.; ierr = SNESSetFunction (_snes, r->vec(), __libmesh_petsc_snes_residual, this); LIBMESH_CHKERRABORT(ierr); // Only set the jacobian function if we've been provided with something to call. // This allows a user to set their own jacobian function if they want to if (this->jacobian || this->jacobian_object || this->residual_and_jacobian_object) { ierr = SNESSetJacobian (_snes, jac->mat(), jac->mat(), __libmesh_petsc_snes_jacobian, this); LIBMESH_CHKERRABORT(ierr); } #if !PETSC_VERSION_LESS_THAN(3,3,0) // Only set the nullspace if we have a way of computing it and the result is non-empty. if (this->nullspace || this->nullspace_object) { MatNullSpace msp; this->build_mat_null_space(this->nullspace_object, this->nullspace, &msp); if (msp) { ierr = MatSetNullSpace(jac->mat(), msp); LIBMESH_CHKERRABORT(ierr); ierr = MatNullSpaceDestroy(&msp); LIBMESH_CHKERRABORT(ierr); } } // Only set the nearnullspace if we have a way of computing it and the result is non-empty. if (this->nearnullspace || this->nearnullspace_object) { MatNullSpace msp = PETSC_NULL; this->build_mat_null_space(this->nearnullspace_object, this->nearnullspace, &msp); if(msp) { ierr = MatSetNearNullSpace(jac->mat(), msp); LIBMESH_CHKERRABORT(ierr); ierr = MatNullSpaceDestroy(&msp); LIBMESH_CHKERRABORT(ierr); } } #endif // Have the Krylov subspace method use our good initial guess rather than 0 KSP ksp; ierr = SNESGetKSP (_snes, &ksp); LIBMESH_CHKERRABORT(ierr); // Set the tolerances for the iterative solver. Use the user-supplied // tolerance for the relative residual & leave the others at default values ierr = KSPSetTolerances (ksp, this->initial_linear_tolerance, PETSC_DEFAULT, PETSC_DEFAULT, this->max_linear_iterations); LIBMESH_CHKERRABORT(ierr); // Set the tolerances for the non-linear solver. ierr = SNESSetTolerances(_snes, this->absolute_residual_tolerance, this->relative_residual_tolerance, this->relative_step_tolerance, this->max_nonlinear_iterations, this->max_function_evaluations); LIBMESH_CHKERRABORT(ierr); //Pull in command-line options KSPSetFromOptions(ksp); SNESSetFromOptions(_snes); if (this->user_presolve) this->user_presolve(this->system()); //Set the preconditioning matrix if(this->_preconditioner) { this->_preconditioner->set_matrix(jac_in); this->_preconditioner->init(); } // ierr = KSPSetInitialGuessNonzero (ksp, PETSC_TRUE); // LIBMESH_CHKERRABORT(ierr); // Older versions (at least up to 2.1.5) of SNESSolve took 3 arguments, // the last one being a pointer to an int to hold the number of iterations required. # if PETSC_VERSION_LESS_THAN(2,2,0) ierr = SNESSolve (_snes, x->vec(), &n_iterations); LIBMESH_CHKERRABORT(ierr); // 2.2.x style #elif PETSC_VERSION_LESS_THAN(2,3,0) ierr = SNESSolve (_snes, x->vec()); LIBMESH_CHKERRABORT(ierr); // 2.3.x & newer style #else ierr = SNESSolve (_snes, PETSC_NULL, x->vec()); LIBMESH_CHKERRABORT(ierr); ierr = SNESGetIterationNumber(_snes,&n_iterations); LIBMESH_CHKERRABORT(ierr); ierr = SNESGetLinearSolveIterations(_snes, &_n_linear_iterations); LIBMESH_CHKERRABORT(ierr); ierr = SNESGetFunctionNorm(_snes,&final_residual_norm); LIBMESH_CHKERRABORT(ierr); #endif // Get and store the reason for convergence SNESGetConvergedReason(_snes, &_reason); //Based on Petsc 2.3.3 documentation all diverged reasons are negative this->converged = (_reason >= 0); this->clear(); STOP_LOG("solve()", "PetscNonlinearSolver"); // return the # of its. and the final residual norm. return std::make_pair(n_iterations, final_residual_norm); }
int main(int argc, char *argv[]) { int ret = 0; int n; int nnz; std::map<unsigned int, MatrixEntry> ar_mat; std::map<unsigned int, double > ar_rhs; double* sln = nullptr; switch(atoi(argv[2])) { case 1: if(read_matrix_and_rhs((char*)"in/linsys-1", n, nnz, ar_mat, ar_rhs) != 0) throw Hermes::Exceptions::Exception("Failed to read the matrix and rhs."); break; case 2: if(read_matrix_and_rhs((char*)"in/linsys-2", n, nnz, ar_mat, ar_rhs) != 0) throw Hermes::Exceptions::Exception("Failed to read the matrix and rhs."); break; case 3: if(read_matrix_and_rhs((char*)"in/linsys-3", n, nnz, ar_mat, ar_rhs) != 0) throw Hermes::Exceptions::Exception("Failed to read the matrix and rhs."); break; } if(strcasecmp(argv[1], "petsc") == 0) { #ifdef WITH_PETSC PetscMatrix<double> mat; PetscVector<double> rhs; build_matrix(n, ar_mat, ar_rhs, &mat, &rhs); PetscLinearMatrixSolver<double> solver(&mat, &rhs); solve(solver, n); sln = new double[mat.get_size()]; memcpy(sln, solver.get_sln_vector(), mat.get_size() * sizeof(double)); #endif } else if(strcasecmp(argv[1], "petsc-block") == 0) { #ifdef WITH_PETSC PetscMatrix<double> mat; PetscVector<double> rhs; build_matrix_block(n, ar_mat, ar_rhs, &mat, &rhs); PetscLinearMatrixSolver<double> solver(&mat, &rhs); solve(solver, n); sln = new double[mat.get_size()]; memcpy(sln, solver.get_sln_vector(), mat.get_size() * sizeof(double)); #endif } else if(strcasecmp(argv[1], "umfpack") == 0) { #ifdef WITH_UMFPACK CSCMatrix<double> mat; SimpleVector<double> rhs; build_matrix(n, ar_mat, ar_rhs, &mat, &rhs); UMFPackLinearMatrixSolver<double> solver(&mat, &rhs); solve(solver, n); sln = new double[mat.get_size()]; memcpy(sln, solver.get_sln_vector(), mat.get_size() * sizeof(double)); #endif } else if(strcasecmp(argv[1], "umfpack-block") == 0) { #ifdef WITH_UMFPACK CSCMatrix<double> mat; SimpleVector<double> rhs; build_matrix_block(n, ar_mat, ar_rhs, &mat, &rhs); UMFPackLinearMatrixSolver<double> solver(&mat, &rhs); mat.export_to_file("matrix", "A", MatrixExportFormat::EXPORT_FORMAT_PLAIN_ASCII); rhs.export_to_file("vector", "b", MatrixExportFormat::EXPORT_FORMAT_PLAIN_ASCII); solve(solver, n); sln = new double[mat.get_size()]; memcpy(sln, solver.get_sln_vector(), mat.get_size() * sizeof(double)); #endif } else if(strcasecmp(argv[1], "paralution") == 0) { #ifdef WITH_PARALUTION ParalutionMatrix<double> mat; ParalutionVector<double> rhs; build_matrix(n, ar_mat, ar_rhs, &mat, &rhs); Hermes::Solvers::IterativeParalutionLinearMatrixSolver<double> solver(&mat, &rhs); if(atoi(argv[2]) != 1) solver.set_solver_type(BiCGStab); solver.set_precond(new ParalutionPrecond<double>(ILU)); // Tested as of 13th August 2013. solver.set_max_iters(atoi(argv[2]) == 1 ? 1 : atoi(argv[2]) == 2 ? 2 : 5); solve(solver, n); sln = new double[mat.get_size()]; memcpy(sln, solver.get_sln_vector(), mat.get_size() * sizeof(double)); #endif } else if(strcasecmp(argv[1], "paralution-block") == 0) { #ifdef WITH_PARALUTION ParalutionMatrix<double> mat; ParalutionVector<double> rhs; build_matrix_block(n, ar_mat, ar_rhs, &mat, &rhs); Hermes::Solvers::IterativeParalutionLinearMatrixSolver<double> solver(&mat, &rhs); solver.set_precond(new ParalutionPrecond<double>(ILU)); solver.set_max_iters(10000); solve(solver, n); sln = new double[mat.get_size()]; memcpy(sln, solver.get_sln_vector(), mat.get_size() * sizeof(double)); #endif } else if(strcasecmp(argv[1], "superlu") == 0) { #ifdef WITH_SUPERLU CSCMatrix<double> mat; SimpleVector<double> rhs; build_matrix(n, ar_mat, ar_rhs, &mat, &rhs); Hermes::Solvers::SuperLUSolver<double> solver(&mat, &rhs); solve(solver, n); sln = new double[mat.get_size()]; memcpy(sln, solver.get_sln_vector(), mat.get_size() * sizeof(double)); #endif } else if(strcasecmp(argv[1], "superlu-block") == 0) { #ifdef WITH_SUPERLU CSCMatrix<double> mat; SimpleVector<double> rhs; build_matrix_block(n, ar_mat, ar_rhs, &mat, &rhs); Hermes::Solvers::SuperLUSolver<double> solver(&mat, &rhs); solve(solver, n); sln = new double[mat.get_size()]; memcpy(sln, solver.get_sln_vector(), mat.get_size() * sizeof(double)); #endif } else if(strcasecmp(argv[1], "aztecoo") == 0) { #ifdef WITH_TRILINOS EpetraMatrix<double> mat; EpetraVector<double> rhs; build_matrix(n, ar_mat, ar_rhs, &mat, &rhs); AztecOOSolver<double> solver(&mat, &rhs); solve(solver, n); sln = new double[mat.get_size()]; memcpy(sln, solver.get_sln_vector(), mat.get_size() * sizeof(double)); #endif } else if(strcasecmp(argv[1], "aztecoo-block") == 0) { #ifdef WITH_TRILINOS EpetraMatrix<double> mat; EpetraVector<double> rhs; build_matrix_block(n, ar_mat, ar_rhs, &mat, &rhs); AztecOOSolver<double> solver(&mat, &rhs); solve(solver, n); sln = new double[mat.get_size()]; memcpy(sln, solver.get_sln_vector(), mat.get_size() * sizeof(double)); #endif } else if(strcasecmp(argv[1], "amesos") == 0) { #ifdef WITH_TRILINOS EpetraMatrix<double> mat; EpetraVector<double> rhs; build_matrix(n, ar_mat, ar_rhs, &mat, &rhs); if(AmesosSolver<double>::is_available("Klu")) { AmesosSolver<double> solver("Klu", &mat, &rhs); solve(solver, n); sln = new double[mat.get_size()]; memcpy(sln, solver.get_sln_vector(), mat.get_size() * sizeof(double)); } #endif } else if(strcasecmp(argv[1], "amesos-block") == 0) { #ifdef WITH_TRILINOS EpetraMatrix<double> mat; EpetraVector<double> rhs; build_matrix_block(n, ar_mat, ar_rhs, &mat, &rhs); if(AmesosSolver<double>::is_available("Klu")) { AmesosSolver<double> solver("Klu", &mat, &rhs); solve(solver, n); sln = new double[mat.get_size()]; memcpy(sln, solver.get_sln_vector(), mat.get_size() * sizeof(double)); } #endif } else if(strcasecmp(argv[1], "mumps") == 0) { #ifdef WITH_MUMPS MumpsMatrix<double> mat; SimpleVector<double> rhs; build_matrix(n, ar_mat, ar_rhs, &mat, &rhs); MumpsSolver<double> solver(&mat, &rhs); solve(solver, n); sln = new double[mat.get_size()]; memcpy(sln, solver.get_sln_vector(), mat.get_size() * sizeof(double)); #endif } else if(strcasecmp(argv[1], "mumps-block") == 0) { #ifdef WITH_MUMPS MumpsMatrix<double> mat; SimpleVector<double> rhs; build_matrix_block(n, ar_mat, ar_rhs, &mat, &rhs); MumpsSolver<double> solver(&mat, &rhs); solve(solver, n); sln = new double[mat.get_size()]; memcpy(sln, solver.get_sln_vector(), mat.get_size() * sizeof(double)); #endif } bool success = true; if(sln) { switch(atoi(argv[2])) { case 1: success = Testing::test_value(sln[0], 4, "sln[0]", 1E-6) && success; success = Testing::test_value(sln[1], 2, "sln[1]", 1E-6) && success; success = Testing::test_value(sln[2], 3, "sln[2]", 1E-6) && success; break; case 2: success = Testing::test_value(sln[0], 2, "sln[0]", 1E-6) && success; success = Testing::test_value(sln[1], 3, "sln[1]", 1E-6) && success; success = Testing::test_value(sln[2], 1, "sln[2]", 1E-6) && success; success = Testing::test_value(sln[3], -3, "sln[3]", 1E-6) && success; success = Testing::test_value(sln[4], -1, "sln[4]", 1E-6) && success; break; case 3: success = Testing::test_value(sln[0], 1, "sln[0]", 1E-6) && success; success = Testing::test_value(sln[1], 2, "sln[1]", 1E-6) && success; success = Testing::test_value(sln[2], 3, "sln[2]", 1E-6) && success; success = Testing::test_value(sln[3], 4, "sln[3]", 1E-6) && success; success = Testing::test_value(sln[4], 5, "sln[4]", 1E-6) && success; break; } delete[] sln; if(success) { printf("Success!\n"); return 0; } else { printf("Failure!\n"); return -1; } } else return 0; }