You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

231 lines
7.0 KiB

//
// AMGCLSolver.hpp
//
#ifdef USE_AMGCL
#include "AMGCLSolver.hpp"
#include <amgcl/io/mm.hpp>
#include <iostream>
namespace SIM {
template <typename vectorTypeI, typename vectorTypeS>
AMGCLSolver<vectorTypeI, vectorTypeS>::AMGCLSolver(void)
{
solver = NULL;
}
template <typename vectorTypeI, typename vectorTypeS>
AMGCLSolver<vectorTypeI, vectorTypeS>::~AMGCLSolver(void)
{
if (solver) {
delete solver;
}
}
template <typename vectorTypeI, typename vectorTypeS>
void AMGCLSolver<vectorTypeI, vectorTypeS>::set_pattern(const std::vector<std::set<int>>& vNeighbor)
{
Base::set_pattern(vNeighbor);
Base::ia.array() -= 1;
Base::ja.array() -= 1;
copyOffDiag_IJ();
}
template <typename vectorTypeI, typename vectorTypeS>
void AMGCLSolver<vectorTypeI, vectorTypeS>::load(const char* filePath, Eigen::VectorXd& rhs)
{
Base::load(filePath, rhs);
Base::ia.array() -= 1;
Base::ja.array() -= 1;
//_ia.resize(Base::ia.size());
//std::memcpy(_ia.data(), Base::ia.data(), Base::ia.size() * sizeof(Base::ia[0]));
//_ja.resize(Base::ja.size());
//std::memcpy(_ja.data(), Base::ja.data(), Base::ja.size() * sizeof(Base::ja[0]));
//_a.resize(Base::a.size());
//std::memcpy(_a.data(), Base::a.data(), Base::a.size() * sizeof(Base::a[0]));
copyOffDiag_IJ();
}
template <typename vectorTypeI, typename vectorTypeS>
void AMGCLSolver<vectorTypeI, vectorTypeS>::load_AMGCL(const char* filePath, Eigen::VectorXd& rhs)
{
int rows, cols, n, m;
std::tie(rows, cols) = amgcl::io::mm_reader(filePath)(_ia, _ja, _a);
Base::numRows = rows;
std::vector<double> rhs_stdv;
std::tie(n, m) = amgcl::io::mm_reader(std::string(filePath) + "_rhs")(rhs_stdv);
rhs.resize(rhs_stdv.size());
std::memcpy(rhs.data(), rhs_stdv.data(), sizeof(rhs_stdv[0]) * rhs_stdv.size());
}
template <typename vectorTypeI, typename vectorTypeS>
void AMGCLSolver<vectorTypeI, vectorTypeS>::write_AMGCL(const char* filePath, const Eigen::VectorXd& rhs) const
{
amgcl::io::mm_write(filePath, std::tie(Base::numRows, _ia, _ja, _a));
amgcl::io::mm_write(std::string(filePath) + "_rhs", rhs.data(), rhs.size());
}
template <typename vectorTypeI, typename vectorTypeS>
void AMGCLSolver<vectorTypeI, vectorTypeS>::copyOffDiag_IJ(void)
{
std::vector<std::vector<int>> ja_new(Base::numRows);
for (int rowI = 0; rowI < Base::numRows; ++rowI) {
int jaStart = Base::ia[rowI];
while (Base::ja[jaStart] < rowI) {
++jaStart;
}
int jaEnd = Base::ia[rowI + 1];
assert(jaEnd >= jaStart);
int curSize = ja_new[rowI].size();
ja_new[rowI].resize(curSize + jaEnd - jaStart);
std::memcpy(ja_new[rowI].data() + curSize, Base::ja.data() + jaStart,
sizeof(Base::ja[0]) * (jaEnd - jaStart));
for (int jaI = jaStart + 1; jaI < jaEnd; ++jaI) {
int colI = Base::ja[jaI];
ja_new[colI].emplace_back(rowI);
}
}
_ia.resize(Base::numRows + 1);
_ia[0] = 0;
_ja.resize(0);
_ja.reserve(Base::ja.size() * 2);
for (int rowI = 0; rowI < Base::numRows; ++rowI) {
_ia[rowI + 1] = _ia[rowI] + ja_new[rowI].size();
_ja.insert(_ja.end(), ja_new[rowI].begin(), ja_new[rowI].end());
}
}
template <typename vectorTypeI, typename vectorTypeS>
void AMGCLSolver<vectorTypeI, vectorTypeS>::copyOffDiag_a(void)
{
std::vector<std::vector<double>> a_new(Base::numRows);
for (int rowI = 0; rowI < Base::numRows; ++rowI) {
int jaStart = Base::ia[rowI];
while (Base::ja[jaStart] < rowI) {
++jaStart;
}
int jaEnd = Base::ia[rowI + 1];
assert(jaEnd >= jaStart);
int curSize = a_new[rowI].size();
a_new[rowI].resize(curSize + jaEnd - jaStart);
std::memcpy(a_new[rowI].data() + curSize, Base::a.data() + jaStart,
sizeof(Base::a[0]) * (jaEnd - jaStart));
for (int jaI = jaStart + 1; jaI < jaEnd; ++jaI) {
int colI = Base::ja[jaI];
a_new[colI].emplace_back(Base::a[jaI]);
}
}
_a.resize(0);
_a.reserve(Base::a.size() * 2);
for (int rowI = 0; rowI < Base::numRows; ++rowI) {
_a.insert(_a.end(), a_new[rowI].begin(), a_new[rowI].end());
}
}
template <typename vectorTypeI, typename vectorTypeS>
void AMGCLSolver<vectorTypeI, vectorTypeS>::analyze_pattern(void)
{
}
template <typename vectorTypeI, typename vectorTypeS>
bool AMGCLSolver<vectorTypeI, vectorTypeS>::factorize(void)
{
// std::cout << getCurrentRSS() << std::endl;
copyOffDiag_a();
if (solver) {
delete solver;
}
Solver::params prm;
prm.solver.tol = 1e-5; // relative
prm.solver.maxiter = 1000;
prm.precond.coarsening.aggr.eps_strong = 0.0;
prm.solver.M = 100;
#ifdef USE_BW_BACKEND
auto A = amgcl::adapter::block_matrix<value_type>(std::tie(Base::numRows, _ia, _ja, _a));
std::cout << A.rows() << " " << A.cols() << std::endl; //NOTE: [a wierd bug] must keep this line as it is
solver = new Solver(A, prm);
#else
#if defined(USE_BW_AGGREGATION)
prm.precond.coarsening.aggr.block_size = 3;
#endif
solver = new Solver(std::tie(Base::numRows, _ia, _ja, _a), prm);
#endif
std::cout << solver->precond() << std::endl;
// std::cout << getCurrentRSS() << std::endl;
// exit(0);
return true;
}
template <typename vectorTypeI, typename vectorTypeS>
void AMGCLSolver<vectorTypeI, vectorTypeS>::solve(Eigen::VectorXd& rhs,
Eigen::VectorXd& result)
{
assert(rhs.size() == Base::numRows);
#ifdef USE_BW_BACKEND ///
result.setZero(Base::numRows);
size_t iters;
double resid;
rhs_type const* fptr = reinterpret_cast<rhs_type const*>(rhs.data());
rhs_type* xptr = reinterpret_cast<rhs_type*>(result.data());
amgcl::backend::numa_vector<rhs_type> F(fptr, fptr + rhs.size() / 3);
amgcl::backend::numa_vector<rhs_type> X(xptr, xptr + result.size() / 3);
#ifdef USE_AMG_SOLVER
solver->precond().cycle(F, X);
#else
std::tie(iters, resid) = (*solver)(F, X);
std::cout << "Iterations: " << iters << std::endl
<< "Error: " << resid << std::endl;
if (resid != resid) {
std::cout << "AMGCL failed!" << std::endl;
Base::write("Mnan", rhs);
write_AMGCL("M", rhs);
exit(-1);
}
#endif
std::copy(X.data(), X.data() + X.size(), xptr);
#else ///
std::vector<double> x(Base::numRows, 0.0), _rhs(Base::numRows);
std::memcpy(_rhs.data(), rhs.data(), sizeof(rhs[0]) * rhs.size());
#ifdef USE_AMG_SOLVER
solver->precond().cycle(_rhs, x);
#else
int iters;
double error;
std::tie(iters, error) = (*solver)(_rhs, x);
std::cout << "Iterations: " << iters << std::endl
<< "Error: " << error << std::endl;
if (error != error) {
std::cout << "AMGCL failed!" << std::endl;
Base::write("Mnan", rhs);
write_AMGCL("M", rhs);
exit(-1);
}
#endif
result.resize(x.size());
std::memcpy(result.data(), x.data(), sizeof(x[0]) * x.size());
#endif ///
}
template class AMGCLSolver<Eigen::VectorXi, Eigen::VectorXd>;
} // namespace SIM
#endif