computation/interfaces/direct/Cholmod.cxx

00001 // Copyright (C) 2010 Marc Duruflé
00002 //
00003 // This file is part of the linear-algebra library Seldon,
00004 // http://seldon.sourceforge.net/.
00005 //
00006 // Seldon is free software; you can redistribute it and/or modify it under the
00007 // terms of the GNU Lesser General Public License as published by the Free
00008 // Software Foundation; either version 2.1 of the License, or (at your option)
00009 // any later version.
00010 //
00011 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
00012 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00013 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
00014 // more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public License
00017 // along with Seldon. If not, see http://www.gnu.org/licenses/.
00018 
00019 
00020 #ifndef SELDON_FILE_CHOLMOD_CXX
00021 
00022 #include "Cholmod.hxx"
00023 
00024 namespace Seldon
00025 {
00026 
00027   MatrixCholmod::MatrixCholmod()
00028   {
00029     // Sets default parameters.
00030     cholmod_start(&param_chol);
00031 
00032     n = 0;
00033   }
00034 
00035 
00036 
00037   MatrixCholmod::~MatrixCholmod()
00038   {
00039     if (n > 0)
00040       {
00041         Clear();
00042         cholmod_finish(&param_chol);
00043       }
00044   }
00045 
00046 
00047   void MatrixCholmod::Clear()
00048   {
00049     if (n > 0)
00050       {
00051         n = 0;
00052         cholmod_free_factor(&L, &param_chol);
00053       }
00054   }
00055 
00056 
00057   template<class Prop, class Storage, class Allocator>
00058   void MatrixCholmod::
00059   FactorizeMatrix(Matrix<double, Prop, Storage, Allocator> & mat,
00060                   bool keep_matrix)
00061   {
00062     Clear();
00063 
00064     n = mat.GetM();
00065     Matrix<double, Symmetric, RowSymSparse, MallocAlloc<double> > Acsc;
00066     Copy(mat, Acsc);
00067     if (!keep_matrix)
00068       mat.Clear();
00069 
00070     // Initialization of sparse matrix.
00071     cholmod_sparse A;
00072 
00073     A.nrow = n;
00074     A.ncol = n;
00075     A.nzmax = Acsc.GetDataSize();
00076     A.nz = NULL;
00077     A.p = Acsc.GetPtr();
00078     A.i = Acsc.GetInd();
00079     A.x = Acsc.GetData();
00080     A.z = NULL;
00081     A.stype = -1;
00082     A.xtype = CHOLMOD_REAL;
00083     A.dtype = CHOLMOD_DOUBLE;
00084     A.sorted = true;
00085     A.packed = true;
00086 
00087     L = cholmod_analyze(&A, &param_chol);
00088 
00089     cholmod_factorize(&A, L, &param_chol);
00090 
00091     cholmod_change_factor(CHOLMOD_REAL, true, L->is_super,
00092                           true, L->is_monotonic, L, &param_chol);
00093   }
00094 
00095 
00096   template<class Transpose_status, class Allocator>
00097   void MatrixCholmod::Solve(const Transpose_status& TransA,
00098                             Vector<double, VectFull, Allocator>& x)
00099   {
00100     // and dense right hand side
00101     cholmod_dense b_rhs;
00102     b_rhs.nrow = x.GetM();
00103     b_rhs.ncol = 1;
00104     b_rhs.nzmax = b_rhs.nrow;
00105     b_rhs.d = b_rhs.nrow;
00106     b_rhs.x = x.GetData();
00107     b_rhs.z = NULL;
00108     b_rhs.xtype = CHOLMOD_REAL;
00109     b_rhs.dtype = CHOLMOD_DOUBLE;
00110 
00111     cholmod_dense* x_sol, *y;
00112     if (TransA.Trans())
00113       {
00114         y = cholmod_solve(CHOLMOD_Lt, L, &b_rhs, &param_chol);
00115         x_sol = cholmod_solve(CHOLMOD_Pt, L, y, &param_chol);
00116       }
00117     else
00118       {
00119         y = cholmod_solve(CHOLMOD_P, L, &b_rhs, &param_chol);
00120         x_sol = cholmod_solve(CHOLMOD_L, L, y, &param_chol);
00121       }
00122 
00123     double* data = reinterpret_cast<double*>(x_sol->x);
00124     for (int i = 0; i < x.GetM(); i++)
00125       x(i) = data[i];
00126 
00127     cholmod_free_dense(&x_sol, &param_chol);
00128     cholmod_free_dense(&y, &param_chol);
00129   }
00130 
00131 
00132   template<class T, class Prop, class Storage, class Allocator>
00133   void GetCholesky(Matrix<T, Prop, Storage, Allocator>& A,
00134                    MatrixCholmod& mat_chol, bool keep_matrix = false)
00135   {
00136     mat_chol.FactorizeMatrix(A, keep_matrix);
00137   }
00138 
00139   template<class T, class Allocator, class Transpose_status>
00140   void
00141   SolveCholesky(const Transpose_status& TransA,
00142                 MatrixCholmod& mat_chol, Vector<T, VectFull, Allocator>& x)
00143   {
00144     mat_chol.Solve(TransA, x);
00145   }
00146 
00147 }
00148 
00149 #define SELDON_FILE_CHOLMOD_CXX
00150 #endif