MasterContactSolver.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
00024 ******************************************************************************/
00025 #include <sofa/component/mastersolver/MasterContactSolver.h>
00026 
00027 #include <sofa/simulation/common/AnimateVisitor.h>
00028 #include <sofa/simulation/common/BehaviorUpdatePositionVisitor.h>
00029 #include <sofa/simulation/common/MechanicalVisitor.h>
00030 #include <sofa/simulation/common/SolveVisitor.h>
00031 
00032 #include <sofa/helper/LCPcalc.h>
00033 
00034 #include <sofa/core/ObjectFactory.h>
00035 
00036 #include <sofa/helper/system/thread/CTime.h>
00037 #include <math.h>
00038 #include <iostream>
00039 
00040 using std::cerr;
00041 using std::endl;
00042 
00043 namespace sofa
00044 {
00045 
00046 namespace component
00047 {
00048 
00049 namespace odesolver
00050 {
00051 
00052 
00053 LCP::LCP(unsigned int mxC) : maxConst(mxC), tol(0.00001), numItMax(1000), useInitialF(true), mu(0.0), dim(0), lok(false)
00054 {
00055     W.resize(maxConst,maxConst);
00056     A.resize(maxConst,2*maxConst+1);
00057     dFree.resize(maxConst);
00058     f.resize(2*maxConst+1);
00059 }
00060 
00061 LCP::~LCP()
00062 {
00063 }
00064 
00065 void LCP::reset(void)
00066 {
00067     W.clear();
00068     W.clear();
00069     dFree.clear();
00070 }
00071 
00072 
00073 
00074 using namespace sofa::defaulttype;
00075 using namespace helper::system::thread;
00076 using namespace core::componentmodel::behavior;
00077 
00078 
00079 
00080 
00081 #define MAX_NUM_CONSTRAINTS 1024
00082 //#define DISPLAY_TIME
00083 
00084 MasterContactSolver::MasterContactSolver()
00085 :initial_guess(initData(&initial_guess, true, "initial_guess","activate LCP results history to improve its resolution performances."))
00086 ,tol( initData(&tol, 0.001, "tolerance", ""))
00087 ,maxIt( initData(&maxIt, 1000, "maxIt", ""))
00088 ,mu( initData(&mu, 0.6, "mu", ""))
00089 ,_mu(0.6)
00090 , lcp1(MAX_NUM_CONSTRAINTS)
00091 , lcp2(MAX_NUM_CONSTRAINTS)
00092 , _A(&lcp1.A)
00093 , _W(&lcp1.W)
00094 , _dFree(&lcp1.dFree)
00095 , _result(&lcp1.f)
00096 , lcp(&lcp1)
00097 {
00098     _numConstraints = 0;
00099     _mu = 0.0;
00100 
00101     _numPreviousContact=0;
00102     _PreviousContactList = (contactBuf *)malloc(MAX_NUM_CONSTRAINTS * sizeof(contactBuf));
00103     _cont_id_list = (long *)malloc(MAX_NUM_CONSTRAINTS * sizeof(long));
00104 }
00105 
00106 void MasterContactSolver::init()
00107 {
00108     getContext()->get<core::componentmodel::behavior::BaseConstraintCorrection>(&constraintCorrections, core::objectmodel::BaseContext::SearchDown);
00109 }
00110 
00111 void MasterContactSolver::build_LCP()
00112 {
00113     _numConstraints = 0;
00114 //std::cout<<" accumulateConstraint "  <<std::endl;
00115 
00116     // mechanical action executed from root node to propagate the constraints
00117     simulation::MechanicalResetConstraintVisitor().execute(context);
00118     _mu = mu.getValue();
00119     simulation::MechanicalAccumulateConstraint(_numConstraints, _mu).execute(context);
00120     _mu = mu.getValue();
00121 
00122 
00123     //std::cout<<" accumulateConstraint_done "  <<std::endl;
00124 
00125     if (_numConstraints > MAX_NUM_CONSTRAINTS)
00126     {
00127         cerr<<endl<<"Error in MasterContactSolver, maximum number of contacts exceeded, "<< _numConstraints/3 <<" contacts detected"<<endl;
00128         exit(-1);
00129     }
00130 
00131     lcp->getMu() = _mu;
00132 
00133     _dFree->resize(_numConstraints);
00134     _W->resize(_numConstraints,_numConstraints);
00135 
00136     MechanicalGetConstraintValueVisitor(_dFree->ptr()).execute(context);
00137 //  simulation::MechanicalComputeComplianceVisitor(_W).execute(context);
00138 
00139     if (this->f_printLog.getValue()) std::cout<<"MasterContactSolver: "<<_numConstraints<<" constraints, mu = "<<_mu<<std::endl;
00140 
00141     //std::cout<<" computeCompliance in "  << constraintCorrections.size()<< " constraintCorrections" <<std::endl;
00142 
00143     for (unsigned int i=0;i<constraintCorrections.size();i++)
00144     {
00145         core::componentmodel::behavior::BaseConstraintCorrection* cc = constraintCorrections[i];
00146         cc->getCompliance(_W);
00147     }
00148     //std::cout<<" computeCompliance_done "  <<std::endl;
00149 
00150     if (initial_guess.getValue())
00151     {
00152         MechanicalGetContactIDVisitor(_cont_id_list).execute(context);
00153         computeInitialGuess();
00154     }
00155 }
00156 
00157 void MasterContactSolver::computeInitialGuess()
00158 {
00159     int numContact = (_mu > 0.0) ? _numConstraints/3 : _numConstraints;
00160 
00161     for (int c=0; c<numContact; c++)
00162     {
00163         if (_mu>0.0){
00164             (*_result)[3*c  ] = 0.0;
00165             (*_result)[3*c+1] = 0.0;
00166             (*_result)[3*c+2] = 0.0;
00167         }
00168         else
00169         {
00170             (*_result)[c] =  0.0;
00171             (*_result)[c+numContact] =  0.0;
00172         }
00173     }
00174 
00175 
00176     for (int c=0; c<numContact; c++)
00177     {
00178         for (unsigned int pc=0; pc<_numPreviousContact; pc++)
00179         {
00180             if (_cont_id_list[c] == _PreviousContactList[pc].id)
00181             {
00182                 if (_mu>0.0){
00183                     (*_result)[3*c  ] = _PreviousContactList[pc].F.x();
00184                     (*_result)[3*c+1] = _PreviousContactList[pc].F.y();
00185                     (*_result)[3*c+2] = _PreviousContactList[pc].F.z();
00186                 }
00187                 else
00188                 {
00189                     (*_result)[c+numContact] =  _PreviousContactList[pc].F.x();
00190                 }
00191             }
00192         }
00193     }
00194 }
00195 
00196 void MasterContactSolver::keepContactForcesValue()
00197 {
00198     _numPreviousContact=0;
00199 
00200     int numContact = (_mu > 0.0) ? _numConstraints/3 : _numConstraints;
00201 
00202     for (int c=0; c<numContact; c++)
00203     {
00204         if (_mu>0.0)
00205         {
00206             if ((*_result)[3*c]>0.0)//((_result[3*c]>0.0)||(_result[3*c+1]>0.0)||(_result[3*c+2]>0.0))
00207             {
00208                 _PreviousContactList[_numPreviousContact].id = (_cont_id_list[c] >= 0) ? _cont_id_list[c] : -_cont_id_list[c];
00209                 _PreviousContactList[_numPreviousContact].F.x() = (*_result)[3*c];
00210                 _PreviousContactList[_numPreviousContact].F.y() = (*_result)[3*c+1];
00211                 _PreviousContactList[_numPreviousContact].F.z() = (*_result)[3*c+2];
00212                 _numPreviousContact++;
00213             }
00214         }
00215         else
00216         {
00217             if ((*_result)[c]>0.0)
00218             {
00219                 _PreviousContactList[_numPreviousContact].id = (_cont_id_list[c] >= 0) ? _cont_id_list[c] : -_cont_id_list[c];
00220                 _PreviousContactList[_numPreviousContact].F.x() = (*_result)[c];
00221                 _numPreviousContact++;
00222             }
00223 
00224         }
00225     }
00226 }
00227 
00228 void MasterContactSolver::step(double dt)
00229 {
00230 
00231     context = dynamic_cast<simulation::tree::GNode *>(this->getContext()); // access to current node
00232 
00233 #ifdef DISPLAY_TIME
00234     CTime *timer = new CTime();
00235     double time = 0;
00236     time = (double) timer->getTime();
00237 #endif
00238 
00239     // Update the BehaviorModels
00240     // Required to allow the RayPickInteractor interaction
00241 
00242     simulation::BehaviorUpdatePositionVisitor updatePos(dt);
00243     context->execute(&updatePos);
00244 
00245 
00246     simulation::MechanicalBeginIntegrationVisitor beginVisitor(dt);
00247     context->execute(&beginVisitor);
00248 
00249     // Free Motion
00250     simulation::SolveVisitor freeMotion(dt);
00251     context->execute(&freeMotion);
00252     simulation::MechanicalPropagateFreePositionVisitor().execute(context);
00253 
00254     core::componentmodel::behavior::BaseMechanicalState::VecId dx_id = core::componentmodel::behavior::BaseMechanicalState::VecId::dx();
00255     simulation::MechanicalVOpVisitor(dx_id).execute( context);
00256     simulation::MechanicalPropagateDxVisitor(dx_id).execute( context);
00257     simulation::MechanicalVOpVisitor(dx_id).execute( context);
00258 
00259 #ifdef DISPLAY_TIME
00260     std::cout<<" Free Motion " << ( (double) timer->getTime() - time)*0.001 <<" ms" <<std::endl;
00261     time = (double) timer->getTime();
00262 #endif
00263 
00264     // Collision detection and response creation
00265     computeCollision();
00266 
00267 #ifdef DISPLAY_TIME
00268     std::cout<<" computeCollision " << ( (double) timer->getTime() - time)*0.001 <<" ms" <<std::endl;
00269     time = (double) timer->getTime();
00270 #endif
00271 //  MechanicalResetContactForceVisitor().execute(context);
00272 
00273     for (unsigned int i=0;i<constraintCorrections.size();i++)
00274     {
00275         core::componentmodel::behavior::BaseConstraintCorrection* cc = constraintCorrections[i];
00276         cc->resetContactForce();
00277     }
00278 
00279     build_LCP();
00280 
00281 #ifdef DISPLAY_TIME
00282     std::cout<<" build_LCP " << ( (double) timer->getTime() - time)*0.001<<" ms" <<std::endl;
00283     time = (double) timer->getTime();
00284 #endif
00285 
00286     double _tol = tol.getValue();
00287     int _maxIt = maxIt.getValue();
00288 
00289     if (_mu > 0.0)
00290     {
00291 
00292         lcp->setNbConst(_numConstraints);
00293         lcp->setTol(_tol);
00294         helper::nlcp_gaussseidel(_numConstraints, _dFree->ptr(), _W->lptr(), _result->ptr(), _mu, _tol, _maxIt, initial_guess.getValue());
00295         if (this->f_printLog.getValue()) helper::afficheLCP(_dFree->ptr(), _W->lptr(), _result->ptr(),_numConstraints);
00296     }
00297     else
00298     {
00299 
00300 //      helper::lcp_lexicolemke(_numConstraints, _dFree->ptr(), _W->lptr(), _A.lptr(), _result->ptr());
00301         helper::gaussSeidelLCP1(_numConstraints, _dFree->ptr(), _W->lptr(), _result->ptr(), _tol, _maxIt);
00302         if (this->f_printLog.getValue()) helper::afficheLCP(_dFree->ptr(), _W->lptr(), _result->ptr(),_numConstraints);
00303     }
00304 
00305 #ifdef DISPLAY_TIME
00306     std::cout<<" solve_LCP" <<( (double) timer->getTime() - time)*0.001<<" ms" <<std::endl;
00307     time = (double) timer->getTime();
00308 #endif
00309 
00310     if (initial_guess.getValue())
00311         keepContactForcesValue();
00312 
00313 
00314 //  MechanicalApplyContactForceVisitor(_result).execute(context);
00315     for (unsigned int i=0;i<constraintCorrections.size();i++)
00316     {
00317         core::componentmodel::behavior::BaseConstraintCorrection* cc = constraintCorrections[i];
00318         cc->applyContactForce(_result);
00319     }
00320 
00321     simulation::MechanicalPropagateAndAddDxVisitor().execute( context);
00322     simulation::MechanicalPropagatePositionAndVelocityVisitor().execute(context);
00323 
00324 
00325 //  MechanicalResetContactForceVisitor().execute(context);
00326     for (unsigned int i=0;i<constraintCorrections.size();i++)
00327     {
00328         core::componentmodel::behavior::BaseConstraintCorrection* cc = constraintCorrections[i];
00329         cc->resetContactForce();
00330     }
00331 #ifdef DISPLAY_TIME
00332     std::cout<<" contactCorrections" <<( (double) timer->getTime() - time)*0.001 <<" ms" <<std::endl;
00333 #endif
00334 
00335 
00336     //switch lcp
00337     //cout << "switch lcp : " << lcp << endl;
00338 
00339     //lcp1.wait();
00340     //lcp1.lock();
00341     //lcp2.wait();
00342     //lcp2.lock();
00343 
00344     lcp = (lcp == &lcp1) ? &lcp2 : &lcp1;
00345     _A =&lcp->A;
00346     _W = &lcp->W;
00347     _dFree = &lcp->dFree;
00348     _result = &lcp->f;
00349 
00350 
00351     //lcp1.unlock();
00352     //lcp2.unlock();
00353     //cout << "new lcp : " << lcp << endl;
00354 
00355     //struct timespec ts;
00356     //ts.tv_sec = 0;
00357     //ts.tv_nsec = 60 *1000 *1000;
00358 //  nanosleep(&ts, NULL);
00359 
00360     simulation::MechanicalEndIntegrationVisitor endVisitor(dt);
00361     context->execute(&endVisitor);
00362 }
00363 
00364 SOFA_DECL_CLASS(MasterContactSolver)
00365 
00366 int MasterContactSolverClass = core::RegisterObject("Constraint solver")
00367 .add< MasterContactSolver >()
00368 ;
00369 
00370 } // namespace odesolver
00371 
00372 } // namespace component
00373 
00374 } // namespace sofa

Generated on Sun Nov 23 03:40:18 2008 for Sofa by  doxygen 1.5.7.1