//----------------------------------------------------------------------------- void EpetraVector::gather(std::vector<double>& x, const std::vector<dolfin::la_index>& indices) const { const std::size_t _size = indices.size(); x.resize(_size); dolfin_assert(x.size() == _size); // Gather values into a vector EpetraVector y; this->gather(y, indices); dolfin_assert(y.size() == _size); const Epetra_FEVector& _y = *(y.vec()); // Copy values into x for (std::size_t i = 0; i < _size; ++i) x[i] = (_y)[0][i]; }
//----------------------------------------------------------------------------- std::size_t EpetraKrylovSolver::solve(EpetraVector& x, const EpetraVector& b) { dolfin_assert(solver); dolfin_assert(_A); dolfin_assert(_P); // Check dimensions const std::size_t M = _A->size(0); const std::size_t N = _A->size(1); if (N != b.size()) { dolfin_error("EpetraKrylovSolver.cpp", "solve linear system using Epetra Krylov solver", "Non-matching dimensions for linear system"); } // Write a message const bool report = parameters["report"]; if (report && dolfin::MPI::process_number() == 0) info("Solving linear system of size %d x %d (Epetra Krylov solver).", M, N); // Reinitialize solution vector if necessary if (x.size() != M) { _A->resize(x, 1); x.zero(); } else if (!parameters["nonzero_initial_guess"]) x.zero(); // Create linear problem Epetra_LinearProblem linear_problem(_A->mat().get(), x.vec().get(), b.vec().get()); // Set-up linear solver solver->SetProblem(linear_problem); // Set output level if (parameters["monitor_convergence"]) { const std::size_t interval = parameters["monitor_interval"]; solver->SetAztecOption(AZ_output, interval); } else solver->SetAztecOption(AZ_output, AZ_none); dolfin_assert(_P); _preconditioner->set(*this, *_P); // Set covergence check method solver->SetAztecOption(AZ_conv, AZ_rhs); // Start solve solver->Iterate(static_cast<int>(parameters["maximum_iterations"]), parameters["relative_tolerance"]); // Check solve status const double* status = solver->GetAztecStatus(); if ((int) status[AZ_why] != AZ_normal) { std::string errorDescription; if( status[AZ_why] == AZ_maxits ) errorDescription = "maximum iters reached"; else if( status[AZ_why] == AZ_loss ) errorDescription = "loss of accuracy"; else if( status[AZ_why] == AZ_ill_cond ) errorDescription = "ill-conditioned"; else if( status[AZ_why] == AZ_breakdown ) errorDescription = "breakdown"; else errorDescription = "unknown error"; std::stringstream message; message << "Epetra (AztecOO) Krylov solver (" << _method << ", " << _preconditioner->name() << ") " << "failed to converge after " << (int)status[AZ_its] << " iterations " << "(" << errorDescription << ", error code " << (int)status[AZ_why] << ")"; if (parameters["error_on_nonconvergence"]) { dolfin_error("EpetraKrylovSolver.cpp", "solve linear system using Epetra Krylov solver", message.str()); } else warning(message.str()); } else { info("Epetra (AztecOO) Krylov solver (%s, %s) converged in %d iterations.", _method.c_str(), _preconditioner->name().c_str(), solver->NumIters()); } // Update residuals absolute_residual = solver->TrueResidual(); relative_residual = solver->ScaledResidual(); // Return number of iterations return solver->NumIters(); }