LULinearSolver.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef SOFA_COMPONENT_LINEARSOLVER_LULINEARSOLVER_H
00026 #define SOFA_COMPONENT_LINEARSOLVER_LULINEARSOLVER_H
00027
00028 #include <sofa/core/componentmodel/behavior/LinearSolver.h>
00029 #include <sofa/simulation/common/MatrixLinearSolver.h>
00030 #include <sofa/component/linearsolver/SparseMatrix.h>
00031 #include <sofa/component/linearsolver/FullMatrix.h>
00032 #include <math.h>
00033
00034 namespace sofa
00035 {
00036
00037 namespace component
00038 {
00039
00040 namespace linearsolver
00041 {
00042
00044 template<class Matrix, class Vector>
00045 class LULinearSolver : public sofa::simulation::MatrixLinearSolver<Matrix,Vector>, public virtual sofa::core::objectmodel::BaseObject
00046 {
00047 public:
00048 Data<bool> f_verbose;
00049 typename Matrix::LUSolver* solver;
00050 typename Matrix::InvMatrixType Minv;
00051 bool computedMinv;
00052
00053 LULinearSolver()
00054 : f_verbose( initData(&f_verbose,false,"verbose","Dump system state at each iteration") )
00055 , solver(NULL), computedMinv(false)
00056 {
00057 }
00058
00059 ~LULinearSolver()
00060 {
00061 if (solver != NULL)
00062 delete solver;
00063 }
00064
00066 void invert (Matrix& M)
00067 {
00068 if (solver != NULL)
00069 delete solver;
00070 solver = M.makeLUSolver();
00071 computedMinv = false;
00072 }
00073
00075 void solve (Matrix& M, Vector& x, Vector& b)
00076 {
00077 using std::cerr;
00078 using std::endl;
00079
00080 const bool verbose = f_verbose.getValue();
00081
00082 if( verbose )
00083 {
00084 cerr<<"LULinearSolver, b = "<< b <<endl;
00085 cerr<<"LULinearSolver, M = "<< M <<endl;
00086 }
00087 if (solver)
00088 M.solve(&x,&b, solver);
00089 else
00090 M.solve(&x,&b);
00091
00092
00093 if( verbose )
00094 {
00095 cerr<<"LULinearSolver::solve, solution = "<<x<<endl;
00096 }
00097 }
00098
00099 void computeMinv()
00100 {
00101 if (!computedMinv)
00102 {
00103 if (solver)
00104 Minv = solver->i();
00105 else
00106 Minv = this->systemMatrix->i();
00107 computedMinv = true;
00108 }
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 }
00119
00120 double getMinvElement(int i, int j)
00121 {
00122 return Minv.element(i,j);
00123 }
00124
00125 template<class RMatrix, class JMatrix>
00126 bool addJMInvJt(RMatrix& result, JMatrix& J, double fact)
00127 {
00128 const int Jrows = J.rowSize();
00129 const int Jcols = J.colSize();
00130 if (Jcols != this->systemMatrix->rowSize())
00131 {
00132 std::cerr << "LULinearSolver::addJMInvJt ERROR: incompatible J matrix size." << std::endl;
00133 return false;
00134 }
00135
00136 if (!Jrows) return false;
00137 computeMinv();
00138
00139 const typename JMatrix::LineConstIterator jitend = J.end();
00140 for (typename JMatrix::LineConstIterator jit1 = J.begin(); jit1 != jitend; ++jit1)
00141 {
00142 int row1 = jit1->first;
00143 for (typename JMatrix::LineConstIterator jit2 = jit1; jit2 != jitend; ++jit2)
00144 {
00145 int row2 = jit2->first;
00146 double acc = 0.0;
00147 for (typename JMatrix::LElementConstIterator i1 = jit1->second.begin(), i1end = jit1->second.end(); i1 != i1end; ++i1)
00148 {
00149 int col1 = i1->first;
00150 double val1 = i1->second;
00151 for (typename JMatrix::LElementConstIterator i2 = jit2->second.begin(), i2end = jit2->second.end(); i2 != i2end; ++i2)
00152 {
00153 int col2 = i2->first;
00154 double val2 = i2->second;
00155 acc += val1 * getMinvElement(col1,col2) * val2;
00156 }
00157 }
00158 acc *= fact;
00159
00160 result.add(row1,row2,acc);
00161 if (row1!=row2)
00162 result.add(row2,row1,acc);
00163 }
00164 }
00165 return true;
00166 }
00167
00173 bool addJMInvJt(defaulttype::BaseMatrix* result, defaulttype::BaseMatrix* J, double fact)
00174 {
00175 if (FullMatrix<double>* r = dynamic_cast<FullMatrix<double>*>(result))
00176 {
00177 if (SparseMatrix<double>* j = dynamic_cast<SparseMatrix<double>*>(J))
00178 {
00179 return addJMInvJt(*r,*j,fact);
00180 }
00181 else if (SparseMatrix<float>* j = dynamic_cast<SparseMatrix<float>*>(J))
00182 {
00183 return addJMInvJt(*r,*j,fact);
00184 }
00185 }
00186 else if (FullMatrix<double>* r = dynamic_cast<FullMatrix<double>*>(result))
00187 {
00188 if (SparseMatrix<double>* j = dynamic_cast<SparseMatrix<double>*>(J))
00189 {
00190 return addJMInvJt(*r,*j,fact);
00191 }
00192 else if (SparseMatrix<float>* j = dynamic_cast<SparseMatrix<float>*>(J))
00193 {
00194 return addJMInvJt(*r,*j,fact);
00195 }
00196 }
00197 else if (defaulttype::BaseMatrix* r = result)
00198 {
00199 if (SparseMatrix<double>* j = dynamic_cast<SparseMatrix<double>*>(J))
00200 {
00201 return addJMInvJt(*r,*j,fact);
00202 }
00203 else if (SparseMatrix<float>* j = dynamic_cast<SparseMatrix<float>*>(J))
00204 {
00205 return addJMInvJt(*r,*j,fact);
00206 }
00207 }
00208 return false;
00209 }
00210
00211 };
00212
00213 }
00214
00215 }
00216
00217 }
00218
00219 #endif