![]() |
MechSys
1.0
Computing library for simulations in continuum and discrete mechanics
|
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