// Copyright (c) 2007-08 INRIA Sophia-Antipolis (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org); you may redistribute it under // the terms of the Q Public License version 1.0. // See the file LICENSE.QPL distributed with CGAL. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL: // $Id: // // Author(s) : Pierre Alliez and Mario Botsch #ifndef CGAL_TAUCS_SOLVER_H #define CGAL_TAUCS_SOLVER_H #include #include #include // Uncomment the next line to see libraries selected by auto-link //#define CGAL_LIB_DIAGNOSTIC #include #include CGAL_BEGIN_NAMESPACE /// CLASS Taucs_solver: /// direct solver for symmetric positive definite sparse systems class Taucs_solver { public: Taucs_solver() : PAP(0), L(0), SL(0), n_rows(0), perm(0), invperm(0), supernodal_(true) { m_io_handle = NULL; //#ifdef DEBUG_TRACE // // Turn on TAUCS trace // std::cerr.flush(); // taucs_logfile((char*)"stderr"); //#endif } ~Taucs_solver() { delete_matrices(); } void begin_row() { if (colptr.empty() || colptr.back() != (int)values.size()) { colptr.push_back((int)values.size()); n_rows = (int)colptr.size()-1; } } void add_value(int _i, double _val, const bool symmetric = true) { if(symmetric) { if(_i <= n_rows) { values.push_back(_val); rowind.push_back(_i); } } else { values.push_back(_val); rowind.push_back(_i); } } void end_row() { if (colptr.empty() || colptr.back() != (int)values.size()) { colptr.push_back((int)values.size()); n_rows = (int)(colptr.size()-1); } } bool factorize(bool _use_supernodal = true) { supernodal_ = _use_supernodal; // delete old matrices delete_matrices(); finalize_matrix(); // bandlimitation taucs_ccs_order(&A, &perm, &invperm, (char*)"metis"); PAP = taucs_ccs_permute_symmetrically(&A, perm, invperm); if (!PAP) { std::cerr << "Taucs_solver: permutation failed\n"; return false; } // Cholesky factorization if (supernodal_) SL = taucs_ccs_factor_llt_mf (PAP); else L = taucs_ccs_factor_llt (PAP, 0, 0); if (!(L || SL)) { std::cerr << "Taucs_solver: factorization failed\n"; return false; } return true; } bool factorize_ooc() { // delete old matrices delete_matrices(); finalize_matrix(); // bandlimitation taucs_ccs_order(&A, &perm, &invperm, (char*)"metis"); PAP = taucs_ccs_permute_symmetrically(&A, perm, invperm); if (!PAP) { std::cerr << "Taucs_solver: permutation failed\n"; return false; } // out-of-core Cholesky factorization. // LS 03/2008: ooc file opening will fail if 2 instances of the application // run at the same time. Better use tempnam(). m_io_handle = taucs_io_create_multifile((char*)"taucs-ooc"); if(m_io_handle == NULL) { //CGAL_surface_reconstruction_assertion(false); std::cerr << "ooc file opening failed\n"; return false; } double available_memory = taucs_available_memory_size(); int result = taucs_ooc_factor_llt(PAP,m_io_handle,available_memory); if(result != TAUCS_SUCCESS) { //CGAL_surface_reconstruction_assertion(false); std::cerr << "ooc factorization failed\n"; return false; } return true; } bool solve(std::vector& _b, std::vector& _x) { const unsigned int N = A.n; if (N != _b.size() || N != _x.size()) { std::cerr << "Taucs_solver: matrix size doesn't match vector size\n"; return false; } std::vector PB(N), PX(N); // permute rhs for (unsigned int i=0; i& _b, std::vector& _x) { const unsigned int N = A.n; if (N != _b.size() || N != _x.size()) { std::cerr << "Taucs_solver: matrix size doesn't match vector size\n"; return false; } std::vector PB(N), PX(N); // permute rhs for (unsigned int i=0; i& _b, std::vector& _x) { double* x = new double[_x.size()]; double* b = new double[_b.size()]; for(unsigned int i=0;i<_b.size();i++) { x[i] = _x[i]; b[i] = _b[i]; } int result = taucs_minres(&A,NULL,NULL,x,b,1000,0.01); delete [] x; delete [] b; if(result == TAUCS_SUCCESS) return true; return false; } bool solve_linear(std::vector& _b, std::vector& _x) { double* x = new double[_x.size()]; double* b = new double[_b.size()]; for(unsigned int i=0;i<_b.size();i++) { x[i] = _x[i]; b[i] = _b[i]; } // char* options[] = { "taucs.factor.LU=true", NULL }; char* options[] = {NULL}; int result = taucs_linsolve(&A,NULL,1,x,b,options,NULL); delete [] x; delete [] b; if(result == TAUCS_SUCCESS) return true; return false; } bool solve_conjugate_gradient(std::vector& b, std::vector& x, const int itermax, const double convergetol) { finalize_matrix(); int result = taucs_conjugate_gradients(&A,NULL,NULL,&x[0],&b[0],itermax,convergetol); return (result == TAUCS_SUCCESS) ? true : false; } bool solve(std::vector& b, std::vector& x, const unsigned int dim) { const unsigned int N = A.n; CGAL_surface_reconstruction_assertion(dim >= 1); if (N != b.size()/dim || N != x.size()/dim) { std::cerr << "Taucs_solver: matrix size doesn't match vector size\n"; return false; } std::vector PB(N); std::vector PX(N); // solver component-wise for (unsigned int c=0;c values; std::vector colptr; std::vector rowind; int n_rows; int *perm, *invperm; bool supernodal_; taucs_io_handle *m_io_handle; }; CGAL_END_NAMESPACE #endif // CGAL_TAUCS_SOLVER_H