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/RungeKutta4Solver.h>
00026 #include <sofa/simulation/common/MechanicalVisitor.h>
00027 #include <sofa/core/ObjectFactory.h>
00028 #include <math.h>
00029
00030
00031 namespace sofa
00032 {
00033
00034 namespace component
00035 {
00036
00037 namespace odesolver
00038 {
00039
00040 using namespace core::componentmodel::behavior;
00041 using namespace sofa::defaulttype;
00042
00043 int RungeKutta4SolverClass = core::RegisterObject("A popular explicit time integrator")
00044 .add< RungeKutta4Solver >()
00045 .addAlias("RungeKutta4")
00046 ;
00047
00048 SOFA_DECL_CLASS(RungeKutta4);
00049
00050
00051 void RungeKutta4Solver::solve(double dt)
00052 {
00053
00054 MultiVector pos(this, VecId::position());
00055 MultiVector vel(this, VecId::velocity());
00056 MultiVector k1a(this, VecId::V_DERIV);
00057 MultiVector k2a(this, VecId::V_DERIV);
00058 MultiVector k3a(this, VecId::V_DERIV);
00059 MultiVector k4a(this, VecId::V_DERIV);
00060 MultiVector& k1v = vel;
00061 MultiVector k2v(this, VecId::V_DERIV);
00062 MultiVector k3v(this, VecId::V_DERIV);
00063 MultiVector k4v(this, VecId::V_DERIV);
00064 MultiVector newX(this, VecId::V_COORD);
00065
00066 const bool log = this->f_printLog.getValue();
00067
00068 double stepBy2 = double(dt / 2.0);
00069 double stepBy3 = double(dt / 3.0);
00070 double stepBy6 = double(dt / 6.0);
00071
00072 double startTime = this->getTime();
00073
00074 addSeparateGravity(dt);
00075
00076
00077 if (log) std::cout << "RK4 Step 1\n";
00078
00079 computeAcc (startTime, k1a, pos, vel);
00080
00081
00082 if (log) std::cout << "RK4 Step 2\n";
00083 #ifdef SOFA_NO_VMULTIOP // unoptimized version
00084 newX = pos;
00085 k2v = vel;
00086 newX.peq(k1v, stepBy2);
00087 k2v.peq(k1a, stepBy2);
00088 #else // single-operation optimization
00089 {
00090 simulation::MechanicalVMultiOpVisitor vmop;
00091 vmop.ops.resize(2);
00092 vmop.ops[0].first = (VecId)newX;
00093 vmop.ops[0].second.push_back(std::make_pair((VecId)pos,1.0));
00094 vmop.ops[0].second.push_back(std::make_pair((VecId)k1v,stepBy2));
00095 vmop.ops[1].first = (VecId)k2v;
00096 vmop.ops[1].second.push_back(std::make_pair((VecId)vel,1.0));
00097 vmop.ops[1].second.push_back(std::make_pair((VecId)k1a,stepBy2));
00098 vmop.execute(this->getContext());
00099 }
00100 #endif
00101
00102 computeAcc ( startTime+stepBy2, k2a, newX, k2v );
00103
00104
00105 if (log) std::cout << "RK4 Step 3\n";
00106 #ifdef SOFA_NO_VMULTIOP // unoptimized version
00107 newX = pos;
00108 k3v = vel;
00109 newX.peq(k2v, stepBy2);
00110 k3v.peq(k2a, stepBy2);
00111 #else // single-operation optimization
00112 {
00113 simulation::MechanicalVMultiOpVisitor vmop;
00114 vmop.ops.resize(2);
00115 vmop.ops[0].first = (VecId)newX;
00116 vmop.ops[0].second.push_back(std::make_pair((VecId)pos,1.0));
00117 vmop.ops[0].second.push_back(std::make_pair((VecId)k2v,stepBy2));
00118 vmop.ops[1].first = (VecId)k3v;
00119 vmop.ops[1].second.push_back(std::make_pair((VecId)vel,1.0));
00120 vmop.ops[1].second.push_back(std::make_pair((VecId)k2a,stepBy2));
00121 vmop.execute(this->getContext());
00122 }
00123 #endif
00124
00125 computeAcc ( startTime+stepBy2, k3a, newX, k3v );
00126
00127
00128 if (log) std::cout << "RK4 Step 4\n";
00129 #ifdef SOFA_NO_VMULTIOP // unoptimized version
00130 newX = pos;
00131 k4v = vel;
00132 newX.peq(k3v, dt);
00133 k4v.peq(k3a, dt);
00134 #else // single-operation optimization
00135 {
00136 simulation::MechanicalVMultiOpVisitor vmop;
00137 vmop.ops.resize(2);
00138 vmop.ops[0].first = (VecId)newX;
00139 vmop.ops[0].second.push_back(std::make_pair((VecId)pos,1.0));
00140 vmop.ops[0].second.push_back(std::make_pair((VecId)k3v,dt));
00141 vmop.ops[1].first = (VecId)k4v;
00142 vmop.ops[1].second.push_back(std::make_pair((VecId)vel,1.0));
00143 vmop.ops[1].second.push_back(std::make_pair((VecId)k3a,dt));
00144 vmop.execute(this->getContext());
00145 }
00146 #endif
00147
00148 computeAcc( startTime+dt, k4a, newX, k4v);
00149
00150 if (log) std::cout << "RK4 Final\n";
00151 #ifdef SOFA_NO_VMULTIOP // unoptimized version
00152 pos.peq(k1v,stepBy6);
00153 vel.peq(k1a,stepBy6);
00154 pos.peq(k2v,stepBy3);
00155 vel.peq(k2a,stepBy3);
00156 pos.peq(k3v,stepBy3);
00157 vel.peq(k3a,stepBy3);
00158 pos.peq(k4v,stepBy6);
00159 vel.peq(k4a,stepBy6);
00160 #else // single-operation optimization
00161 {
00162 simulation::MechanicalVMultiOpVisitor vmop;
00163 vmop.ops.resize(2);
00164 vmop.ops[0].first = (VecId)pos;
00165 vmop.ops[0].second.push_back(std::make_pair((VecId)pos,1.0));
00166 vmop.ops[0].second.push_back(std::make_pair((VecId)k1v,stepBy6));
00167 vmop.ops[0].second.push_back(std::make_pair((VecId)k2v,stepBy3));
00168 vmop.ops[0].second.push_back(std::make_pair((VecId)k3v,stepBy3));
00169 vmop.ops[0].second.push_back(std::make_pair((VecId)k4v,stepBy6));
00170 vmop.ops[1].first = (VecId)vel;
00171 vmop.ops[1].second.push_back(std::make_pair((VecId)vel,1.0));
00172 vmop.ops[1].second.push_back(std::make_pair((VecId)k1a,stepBy6));
00173 vmop.ops[1].second.push_back(std::make_pair((VecId)k2a,stepBy3));
00174 vmop.ops[1].second.push_back(std::make_pair((VecId)k3a,stepBy3));
00175 vmop.ops[1].second.push_back(std::make_pair((VecId)k4a,stepBy6));
00176 vmop.execute(this->getContext());
00177 }
00178 #endif
00179 }
00180
00181
00182
00183 }
00184
00185 }
00186
00187 }
00188