bool EigenLisLinearSolver::solve(EigenMatrix &A_, EigenVector& b_, EigenVector &x_) { static_assert(EigenMatrix::RawMatrixType::IsRowMajor, "Sparse matrix is required to be in row major storage."); auto &A = A_.getRawMatrix(); auto &b = b_.getRawVector(); auto &x = x_.getRawVector(); if (!A.isCompressed()) A.makeCompressed(); int nnz = A.nonZeros(); int* ptr = A.outerIndexPtr(); int* col = A.innerIndexPtr(); double* data = A.valuePtr(); LisMatrix lisA(A_.getNumberOfRows(), nnz, ptr, col, data); LisVector lisb(b.rows(), b.data()); LisVector lisx(x.rows(), x.data()); LisLinearSolver lissol; // TODO not always creat Lis solver here lissol.setOption(_lis_option); lissol.solve(lisA, lisb, lisx); for (std::size_t i=0; i<lisx.size(); i++) x[i] = lisx[i]; return true; // TODO implement checks }
bool EigenLinearSolver::solve(EigenMatrix &A, EigenVector& b, EigenVector &x) { INFO("------------------------------------------------------------------"); INFO("*** Eigen solver computation"); #ifdef USE_EIGEN_UNSUPPORTED std::unique_ptr<Eigen::IterScaling<EigenMatrix::RawMatrixType>> scal; if (_option.scaling) { INFO("-> scale"); scal.reset(new Eigen::IterScaling<EigenMatrix::RawMatrixType>()); scal->computeRef(A.getRawMatrix()); b.getRawVector() = scal->LeftScaling().cwiseProduct(b.getRawVector()); } #endif auto const success = _solver->solve(A.getRawMatrix(), b.getRawVector(), x.getRawVector(), _option); #ifdef USE_EIGEN_UNSUPPORTED if (scal) x.getRawVector() = scal->RightScaling().cwiseProduct(x.getRawVector()); #endif INFO("------------------------------------------------------------------"); return success; }
//--------------------------------------------------------------------------- int main(int argc, char *argv[]) { namespace po = boost::program_options; try { std::string ifile; std::string ofile = "partition.mtx"; int nparts, block_size; po::options_description desc("Options"); desc.add_options() ("help,h", "show help") ("input,i", po::value<std::string>(&ifile)->required(), "Input matrix") ("output,o", po::value<std::string>(&ofile)->default_value(ofile), "Output file") ("nparts,n", po::value<int>(&nparts)->required(), "Number of parts") ("block_size,b", po::value<int>(&block_size)->default_value(1), "Block size") ; po::positional_options_description pd; pd.add("input", 1); po::variables_map vm; po::store(po::command_line_parser(argc, argv).options(desc).positional(pd).run(), vm); if (vm.count("help")) { std::cout << desc << std::endl; return 0; } po::notify(vm); EigenMatrix A; precondition( Eigen::loadMarket(A, ifile), "Failed to load matrix file" ); PartVector part = partition(A.rows(), nparts, block_size, A.outerIndexPtr(), A.innerIndexPtr()); precondition( Eigen::saveMarketVector(part, ofile), "Failed to write partition data" ); } catch (const std::exception &e) { std::cerr << "Error: " << e.what() << std::endl; return 1; } }
void addToMatrix(EigenMatrix& m, std::initializer_list<double> values) { auto const rows = m.getNumberOfRows(); auto const cols = m.getNumberOfColumns(); assert(static_cast<EigenMatrix::IndexType>(values.size()) == rows*cols); Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> tmp(rows, cols); auto it = values.begin(); for (GlobalIndexType r=0; r<rows; ++r) { for (GlobalIndexType c=0; c<cols; ++c) { tmp(r, c) = *(it++); } } m.getRawMatrix() += tmp.sparseView(); }
EigenLinearSolver::EigenLinearSolver(EigenMatrix &A, const std::string /*solver_name*/, BaseLib::ConfigTree const*const option) { if (option) setOption(*option); if (!A.getRawMatrix().isCompressed()) A.getRawMatrix().makeCompressed(); if (_option.solver_type==EigenOption::SolverType::SparseLU) { using SolverType = Eigen::SparseLU<EigenMatrix::RawMatrixType, Eigen::COLAMDOrdering<int>>; _solver = new details::EigenDirectLinearSolver<SolverType, IEigenSolver>(A.getRawMatrix()); } else if (_option.solver_type==EigenOption::SolverType::BiCGSTAB) { using SolverType = Eigen::BiCGSTAB<EigenMatrix::RawMatrixType, Eigen::DiagonalPreconditioner<double>>; _solver = new details::EigenIterativeLinearSolver<SolverType, IEigenSolver>(A.getRawMatrix()); } else if (_option.solver_type==EigenOption::SolverType::CG) { using SolverType = Eigen::ConjugateGradient<EigenMatrix::RawMatrixType, Eigen::Lower, Eigen::DiagonalPreconditioner<double>>; _solver = new details::EigenIterativeLinearSolver<SolverType, IEigenSolver>(A.getRawMatrix()); } }
bool Eigen::solve(SLE& system, base::DataMatrix& B, base::DataMatrix& X) const { #ifdef USE_EIGEN Printer::getInstance().printStatusBegin("Solving linear system (Eigen)..."); const size_t n = system.getDimension(); EigenMatrix A = EigenMatrix::Zero(n, n); size_t nnz = 0; // parallelize only if the system is cloneable #pragma omp parallel if (system.isCloneable()) shared(system, A, nnz) default(none) { SLE* system2 = &system; #ifdef _OPENMP std::unique_ptr<CloneableSLE> clonedSLE; if (system.isCloneable() && (omp_get_max_threads() > 1)) { dynamic_cast<CloneableSLE&>(system).clone(clonedSLE); system2 = clonedSLE.get(); } #endif /* _OPENMP */ // copy system matrix to Eigen matrix object #pragma omp for ordered schedule(dynamic) for (size_t i = 0; i < n; i++) { for (size_t j = 0; j < n; j++) { A(i, j) = system2->getMatrixEntry(i, j); // count nonzero entries // (not necessary, you can also remove that if you like) if (A(i, j) != 0) { #pragma omp atomic nnz++; } } // status message if (i % 100 == 0) { #pragma omp ordered { char str[10]; snprintf(str, sizeof(str), "%.1f%%", static_cast<float_t>(i) / static_cast<float_t>(n) * 100.0); Printer::getInstance().printStatusUpdate("constructing matrix (" + std::string(str) + ")"); } } } } Printer::getInstance().printStatusUpdate("constructing matrix (100.0%)"); Printer::getInstance().printStatusNewLine(); // print ratio of nonzero entries { char str[10]; float_t nnz_ratio = static_cast<float_t>(nnz) / (static_cast<float_t>(n) * static_cast<float_t>(n)); snprintf(str, sizeof(str), "%.1f%%", nnz_ratio * 100.0); Printer::getInstance().printStatusUpdate("nnz ratio: " + std::string(str)); Printer::getInstance().printStatusNewLine(); } // calculate QR factorization of system matrix Printer::getInstance().printStatusUpdate("step 1: Householder QR factorization"); ::Eigen::HouseholderQR<EigenMatrix> A_QR = A.householderQr(); base::DataVector x(n); base::DataVector b(n); X.resize(n, B.getNcols()); // solve system for each RHS for (size_t i = 0; i < B.getNcols(); i++) { B.getColumn(i, b); Printer::getInstance().printStatusNewLine(); if (B.getNcols() == 1) { Printer::getInstance().printStatusUpdate("step 2: solving"); } else { Printer::getInstance().printStatusUpdate("step 2: solving (RHS " + std::to_string(i + 1) + " of " + std::to_string(B.getNcols()) + ")"); } if (solveInternal(A, A_QR, b, x)) { X.setColumn(i, x); } else { Printer::getInstance().printStatusEnd("error: Could not solve linear system!"); return false; } } Printer::getInstance().printStatusEnd(); return true; #else std::cerr << "Error in sle_solver::Eigen::solve: " << "SG++ was compiled without Eigen support!\n"; return false; #endif /* USE_EIGEN */ }
void setMatrix(EigenMatrix& m, Eigen::MatrixXd const& tmp) { m.getRawMatrix() = tmp.sparseView(); }