void NewtonIterationBlackoilInterleaved::formInterleavedSystem(const std::vector<ADB>& eqs, const Eigen::SparseMatrix<double, Eigen::RowMajor>& A, Mat& istlA) const { const int np = eqs.size(); // Find sparsity structure as union of basic block sparsity structures, // corresponding to the jacobians with respect to pressure. // Use addition to get to the union structure. Eigen::SparseMatrix<double> structure = eqs[0].derivative()[0]; for (int phase = 0; phase < np; ++phase) { structure += eqs[phase].derivative()[0]; } Eigen::SparseMatrix<double, Eigen::RowMajor> s = structure; // Create ISTL matrix with interleaved rows and columns (block structured). assert(np == 3); istlA.setSize(s.rows(), s.cols(), s.nonZeros()); istlA.setBuildMode(Mat::row_wise); const int* ia = s.outerIndexPtr(); const int* ja = s.innerIndexPtr(); for (Mat::CreateIterator row = istlA.createbegin(); row != istlA.createend(); ++row) { int ri = row.index(); for (int i = ia[ri]; i < ia[ri + 1]; ++i) { row.insert(ja[i]); } } const int size = s.rows(); Span span[3] = { Span(size, 1, 0), Span(size, 1, size), Span(size, 1, 2*size) }; for (int row = 0; row < size; ++row) { for (int col_ix = ia[row]; col_ix < ia[row + 1]; ++col_ix) { const int col = ja[col_ix]; MatrixBlockType block; for (int p1 = 0; p1 < np; ++p1) { for (int p2 = 0; p2 < np; ++p2) { block[p1][p2] = A.coeff(span[p1][row], span[p2][col]); } } istlA[row][col] = block; } } }
LinearSolverISTL::LinearSolverResults LinearSolverISTL::solve(int size, int nonzeros, const int* ia, const int* ja, const double* sa, const double* rhs, double* solution) { // Build ISTL structures from input. // System matrix Mat A(size, size, nonzeros, Mat::row_wise); for (Mat::CreateIterator row = A.createbegin(); row != A.createend(); ++row) { int ri = row.index(); for (int i = ia[ri]; i < ia[ri + 1]; ++i) { row.insert(ja[i]); } } for (int ri = 0; ri < size; ++ri) { for (int i = ia[ri]; i < ia[ri + 1]; ++i) { A[ri][ja[i]] = sa[i]; } } // System RHS Vector b(size); std::copy(rhs, rhs + size, b.begin()); // System solution Vector x(size); x = 0.0; if (linsolver_save_system_) { // Save system to files. writeMatrixToMatlab(A, linsolver_save_filename_ + "-mat"); std::string rhsfile(linsolver_save_filename_ + "-rhs"); std::ofstream rhsf(rhsfile.c_str()); rhsf.precision(15); rhsf.setf(std::ios::scientific | std::ios::showpos); std::copy(b.begin(), b.end(), std::ostream_iterator<VectorBlockType>(rhsf, "\n")); } int maxit = linsolver_max_iterations_; if (maxit == 0) { maxit = A.N(); } LinearSolverResults res; switch (linsolver_type_) { case CG_ILU0: res = solveCG_ILU0(A, x, b, linsolver_residual_tolerance_, maxit, linsolver_verbosity_); break; case CG_AMG: res = solveCG_AMG(A, x, b, linsolver_residual_tolerance_, maxit, linsolver_verbosity_); break; case BiCGStab_ILU0: res = solveBiCGStab_ILU0(A, x, b, linsolver_residual_tolerance_, maxit, linsolver_verbosity_); break; default: std::cerr << "Unknown linsolver_type: " << int(linsolver_type_) << '\n'; throw std::runtime_error("Unknown linsolver_type"); } std::copy(x.begin(), x.end(), solution); return res; }
LinearSolverInterface::LinearSolverReport LinearSolverIstl::solve(const int size, const int nonzeros, const int* ia, const int* ja, const double* sa, const double* rhs, double* solution) const { // Build Istl structures from input. // System matrix Mat A(size, size, nonzeros, Mat::row_wise); for (Mat::CreateIterator row = A.createbegin(); row != A.createend(); ++row) { int ri = row.index(); for (int i = ia[ri]; i < ia[ri + 1]; ++i) { row.insert(ja[i]); } } for (int ri = 0; ri < size; ++ri) { for (int i = ia[ri]; i < ia[ri + 1]; ++i) { A[ri][ja[i]] = sa[i]; } } // System RHS Vector b(size); std::copy(rhs, rhs + size, b.begin()); // System solution Vector x(size); x = 0.0; if (linsolver_save_system_) { // Save system to files. writeMatrixToMatlab(A, linsolver_save_filename_ + "-mat"); std::string rhsfile(linsolver_save_filename_ + "-rhs"); std::ofstream rhsf(rhsfile.c_str()); rhsf.precision(15); rhsf.setf(std::ios::scientific | std::ios::showpos); std::copy(b.begin(), b.end(), std::ostream_iterator<VectorBlockType>(rhsf, "\n")); } int maxit = linsolver_max_iterations_; if (maxit == 0) { maxit = 5000; } LinearSolverReport res; switch (linsolver_type_) { case CG_ILU0: res = solveCG_ILU0(A, x, b, linsolver_residual_tolerance_, maxit, linsolver_verbosity_); break; case CG_AMG: res = solveCG_AMG(A, x, b, linsolver_residual_tolerance_, maxit, linsolver_verbosity_); break; case KAMG: #ifdef HAS_DUNE_FAST_AMG res = solveKAMG(A, x, b, linsolver_residual_tolerance_, maxit, linsolver_verbosity_); #else throw std::runtime_error("KAMG not supported with this version of DUNE"); #endif break; case FastAMG: #ifdef HAS_DUNE_FAST_AMG res = solveFastAMG(A, x, b, linsolver_residual_tolerance_, maxit, linsolver_verbosity_); #else if(linsolver_verbosity_) std::cerr<<"Fast AMG is not available; falling back to CG preconditioned with the normal one"<<std::endl; res = solveCG_AMG(A, x, b, linsolver_residual_tolerance_, maxit, linsolver_verbosity_); #endif break; case BiCGStab_ILU0: res = solveBiCGStab_ILU0(A, x, b, linsolver_residual_tolerance_, maxit, linsolver_verbosity_); break; default: std::cerr << "Unknown linsolver_type: " << int(linsolver_type_) << '\n'; throw std::runtime_error("Unknown linsolver_type"); } std::copy(x.begin(), x.end(), solution); return res; }