CentralDifferenceSolver.cpp
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 #include <sofa/component/odesolver/CentralDifferenceSolver.h>
00026 #include <sofa/simulation/common/MechanicalVisitor.h>
00027 #include <sofa/core/ObjectFactory.h>
00028 #include <math.h>
00029 #include <iostream>
00030 #include "sofa/helper/system/thread/CTime.h"
00031
00032 using std::cerr;
00033 using std::endl;
00034
00035 namespace sofa
00036 {
00037
00038 namespace component
00039 {
00040
00041 namespace odesolver
00042 {
00043
00044 using namespace sofa::defaulttype;
00045 using namespace core::componentmodel::behavior;
00046
00047 CentralDifferenceSolver::CentralDifferenceSolver()
00048 : f_rayleighMass( initData(&f_rayleighMass,0.1,"rayleighMass","Rayleigh damping coefficient related to mass"))
00049 {
00050 }
00051
00087 void CentralDifferenceSolver::solve(double dt)
00088 {
00089 MultiVector pos(this, VecId::position());
00090 MultiVector vel(this, VecId::velocity());
00091 MultiVector f(this, VecId::force());
00092 MultiVector dx(this, VecId::dx());
00093 const double r = f_rayleighMass.getValue();
00094
00095 addSeparateGravity(dt);
00096
00097
00098
00099
00100 computeForce(f);
00101
00102 accFromF(dx, f);
00103
00104 projectResponse(dx);
00105
00106
00107 if (r==0)
00108 {
00109 #ifdef SOFA_NO_VMULTIOP // unoptimized version
00110 vel.peq( dx, dt );
00111 pos.peq( vel, dt );
00112 #else // single-operation optimization
00113 simulation::MechanicalVMultiOpVisitor vmop;
00114 vmop.ops.resize(2);
00115
00116 vmop.ops[0].first = (VecId)vel;
00117 vmop.ops[0].second.push_back(std::make_pair((VecId)vel,1.0));
00118 vmop.ops[0].second.push_back(std::make_pair((VecId)dx,dt));
00119
00120 vmop.ops[1].first = (VecId)pos;
00121 vmop.ops[1].second.push_back(std::make_pair((VecId)pos,1.0));
00122 vmop.ops[1].second.push_back(std::make_pair((VecId)vel,dt));
00123 vmop.execute(getContext());
00124 #endif
00125 }
00126 else
00127 {
00128 #ifdef SOFA_NO_VMULTIOP // unoptimized version
00129 vel.teq( (1/dt - r/2)/(1/dt + r/2) );
00130 vel.peq( dx, 1/(1/dt + r/2) );
00131 pos.peq( vel, dt );
00132 #else // single-operation optimization
00133 simulation::MechanicalVMultiOpVisitor vmop;
00134 vmop.ops.resize(2);
00135 vmop.ops[0].first = (VecId)vel;
00136 vmop.ops[0].second.push_back(std::make_pair((VecId)vel,(1/dt - r/2)/(1/dt + r/2)));
00137 vmop.ops[0].second.push_back(std::make_pair((VecId)dx,1/(1/dt + r/2)));
00138 vmop.ops[1].first = (VecId)pos;
00139 vmop.ops[1].second.push_back(std::make_pair((VecId)pos,1.0));
00140 vmop.ops[1].second.push_back(std::make_pair((VecId)vel,dt));
00141 vmop.execute(getContext());
00142 #endif
00143 }
00144 }
00145
00146 SOFA_DECL_CLASS(CentralDifferenceSolver)
00147
00148 int CentralDifferenceSolverClass = core::RegisterObject("Explicit time integrator using central difference (also known as Verlet of Leap-frop)")
00149 .add< CentralDifferenceSolver >()
00150 .addAlias("CentralDifference");
00151 ;
00152
00153 }
00154
00155 }
00156
00157 }
00158