MechSys  1.0
Computing library for simulations in continuum and discrete mechanics
/home/dorival/mechsys/lib/linalg/umfpack.h
Go to the documentation of this file.
00001 /************************************************************************
00002  * MechSys - Open Library for Mechanical Systems                        *
00003  * Copyright (C) 2005 Dorival M. Pedroso, Raul Durand                   *
00004  * Copyright (C) 2009 Sergio Galindo                                    *
00005  *                                                                      *
00006  * This program is free software: you can redistribute it and/or modify *
00007  * it under the terms of the GNU General Public License as published by *
00008  * the Free Software Foundation, either version 3 of the License, or    *
00009  * any later version.                                                   *
00010  *                                                                      *
00011  * This program is distributed in the hope that it will be useful,      *
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the         *
00014  * GNU General Public License for more details.                         *
00015  *                                                                      *
00016  * You should have received a copy of the GNU General Public License    *
00017  * along with this program. If not, see <http://www.gnu.org/licenses/>  *
00018  ************************************************************************/
00019 
00020 #ifndef MECHSYS_UMFPACK_H
00021 #define MECHSYS_UMFPACK_H
00022 
00023 // Std Lib
00024 #include <cmath> // for pow
00025 
00026 // UMFPACK
00027 extern "C" {
00028 #include <umfpack.h>
00029 }
00030 
00031 // MechSys
00032 #include <mechsys/linalg/matvec.h>
00033 #include <mechsys/linalg/sparse_triplet.h>
00034 #include <mechsys/linalg/sparse_matrix.h>
00035 #include <mechsys/util/fatal.h>
00036 #include <mechsys/util/util.h>
00037 
00038 #ifdef DO_DEBUG
00039   using std::cout;
00040   using std::endl;
00041 #endif
00042 
00050 namespace UMFPACK
00051 {
00052 
00056 String ErrorMsg(int info)
00057 {
00058     switch (info)
00059     {
00060         case UMFPACK_ERROR_out_of_memory           : return String("UMFPACK_ERROR_out_of_memory (-1)");
00061         case UMFPACK_ERROR_invalid_Numeric_object  : return String("UMFPACK_ERROR_invalid_Numeric_object (-3)");
00062         case UMFPACK_ERROR_invalid_Symbolic_object : return String("UMFPACK_ERROR_invalid_Symbolic_object (-4)");
00063         case UMFPACK_ERROR_argument_missing        : return String("UMFPACK_ERROR_argument_missing (-5)");
00064         case UMFPACK_ERROR_n_nonpositive           : return String("UMFPACK_ERROR_n_nonpositive (-6)");
00065         case UMFPACK_ERROR_invalid_matrix          : return String("UMFPACK_ERROR_invalid_matrix (-8)");
00066         case UMFPACK_ERROR_different_pattern       : return String("UMFPACK_ERROR_different_pattern (-11)");
00067         case UMFPACK_ERROR_invalid_system          : return String("UMFPACK_ERROR_invalid_system (-13)");
00068         case UMFPACK_ERROR_invalid_permutation     : return String("UMFPACK_ERROR_invalid_permutation (-15)");
00069         case UMFPACK_ERROR_internal_error          : return String("UMFPACK_ERROR_internal_error (-911)");
00070         case UMFPACK_ERROR_file_IO                 : return String("UMFPACK_ERROR_file_IO (-17)");
00071         default                                    : { String r; r.Printf("Unknown UMFPACK_ERROR (%d)",info); return r; };
00072     }
00073 }
00074 
00080 inline void Solve (Sparse::Matrix<double,int> const & A, Vec_t const & B, Vec_t & X)
00081 {
00082     if (A.Rows()!=A.Cols())        throw new Fatal("UMFPACK::Solve: A (%d x %d) matrix must be squared.",A.Rows(),A.Cols());
00083     if (size(B)!=(size_t)A.Cols()) throw new Fatal("UMFPACK::Solve: B (%d x 1) vector must have a size equal to the number of columns of matrix A (%d)",size(B),A.Cols());
00084     if (size(X)!=size(B))          throw new Fatal("UMFPACK::Solve: X (%d x 1) vector must have the same size as B (%d)",size(X),size(B));
00085     double *null = (double *)NULL;
00086     void *symbolic, *numeric;
00087     int info = 0;
00088     info = umfpack_di_symbolic      (A.Rows(), A.Rows(), A.GetApPtr(), A.GetAiPtr(), A.GetAxPtr(), &symbolic, null, null);      if (info<0) throw new Fatal("UMFPACK::Solve: umfpack_di_symbolic failed. %s",ErrorMsg(info).CStr());
00089     info = umfpack_di_numeric       (A.GetApPtr(), A.GetAiPtr(), A.GetAxPtr(), symbolic, &numeric, null, null);                 if (info<0) throw new Fatal("UMFPACK::Solve: umfpack_di_numeric failed. %s",ErrorMsg(info).CStr());
00090            umfpack_di_free_symbolic (&symbolic);
00091     info = umfpack_di_solve         (UMFPACK_A, A.GetApPtr(), A.GetAiPtr(), A.GetAxPtr(), X.data, B.data, numeric, null, null); if (info<0) throw new Fatal("UMFPACK::Solve: umfpack_di_solve failed. %s",ErrorMsg(info).CStr());
00092            umfpack_di_free_numeric  (&numeric);
00093 }
00094 // TODO: Check: It seems that the following is not necessary
00095 //       (A sparse matrix is automatically created from the Triplet)
00096 inline void Solve (Sparse::Triplet<double,int> const & A, Vec_t const & B, Vec_t & X) { Solve(Sparse::Matrix<double,int>(A), B, X); }
00097 
00098 inline double Det (Sparse::Matrix<double,int> const & A)
00099 {
00100     double *null = (double *)NULL;
00101     void   *symbolic, *numeric;
00102     int    info = 0;
00103     double Mx, Ex;
00104     info = umfpack_di_symbolic        (A.Rows(), A.Rows(), A.GetApPtr(), A.GetAiPtr(), A.GetAxPtr(), &symbolic, null, null);  if (info<0) throw new Fatal("UMFPACK::Det: umfpack_di_symbolic failed. %s",ErrorMsg(info).CStr());
00105     info = umfpack_di_numeric         (A.GetApPtr(), A.GetAiPtr(), A.GetAxPtr(), symbolic, &numeric, null, null);             if (info<0) throw new Fatal("UMFPACK::Det: umfpack_di_numeric failed. %s",ErrorMsg(info).CStr());
00106            umfpack_di_free_symbolic   (&symbolic);
00107     info = umfpack_di_get_determinant (&Mx, &Ex, numeric, null);                                                              if (info<0) throw new Fatal("UMFPACK::Det: umfpack_di_numeric failed. %s",ErrorMsg(info).CStr());
00108     return Mx * pow (10.0, Ex);
00109 }
00110 
00111 class Sys
00112 {
00113 public:
00114     Sys (Sparse::Triplet<double,int> const & Atri)
00115     {
00116         if (Atri.Rows()!=Atri.Cols()) throw new Fatal("UMFPACK::Sys: A (%d x %d) matrix (triplet) must be square",Atri.Rows(),Atri.Cols());
00117         _A = new Sparse::Matrix<double,int> (Atri);
00118         double * null = (double*)NULL;
00119         int info = 0;
00120         info = umfpack_di_symbolic (_A->Rows(), _A->Rows(), _A->GetApPtr(), _A->GetAiPtr(), _A->GetAxPtr(), &_symbolic, null, null);  if (info<0) throw new Fatal("UMFPACK::Sys: umfpack_di_symbolic failed. %s",ErrorMsg(info).CStr());
00121         info = umfpack_di_numeric  (_A->GetApPtr(), _A->GetAiPtr(), _A->GetAxPtr(), _symbolic, &_numeric, null, null);                if (info<0) throw new Fatal("UMFPACK::Sys: umfpack_di_numeric failed. %s",ErrorMsg(info).CStr());
00122     }
00123     ~Sys () { delete _A; umfpack_di_free_symbolic(&_symbolic);  umfpack_di_free_numeric(&_numeric); }
00124     void Solve (Vec_t const & B, Vec_t & X)
00125     {
00126         if (size(B)!=(size_t)_A->Cols()) throw new Fatal("UMFPACK::Sys::Solve: B (%d x 1) vector must have a size equal to the number of columns of matrix A (%d)",size(B),_A->Cols());
00127         if (size(X)!=size(B))            throw new Fatal("UMFPACK::Sys::Solve: X (%d x 1) vector must have the same size as B (%d)",size(X),size(B));
00128         double * null = (double*)NULL;
00129         int info = umfpack_di_solve (UMFPACK_A, _A->GetApPtr(), _A->GetAiPtr(), _A->GetAxPtr(), X.data, B.data, _numeric, null, null); if (info<0) throw new Fatal("UMFPACK::Sys::Solve: umfpack_di_solve failed. %s",ErrorMsg(info).CStr());
00130     }
00131 private:
00132     Sparse::Matrix<double,int> * _A;
00133     void                       * _symbolic;
00134     void                       * _numeric;
00135 };
00136 
00137 }; // namespace UMFPACK
00138 
00139 #endif // MECHSYS_UMFPACK_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines