#include "Euler.h"
rab::Euler::Euler()
{
currentSimTime=0;
}
rab::Euler::Euler(rab::vector3D startFval)
{
currentSimTime=0;
tees.push_back(0);
effs.push_back(startFval);
}
void rab::Euler::clearHistory()
{
currentSimTime=0;
tees.clear();
effs.clear();
}
void rab::Euler::setStartEff(rab::vector3D startFval)
{
if(effs.empty())
{
tees.push_back(0);
effs.push_back(startFval);
}
}
void rab::Euler::setStepLength(double t)
{
if(t>0) stepLength=t;
else stepLength=1;
}
vector<double> rab::Euler::getTees()
{
return tees;
}
vector<rab::vector3D> rab::Euler::getEffs()
{
return effs;
}
void rab::Euler::updateTo(double d)
{
while(currentSimTime<d)
{
step();
}
}
rab::vector3D rab::Euler::evaluateAt(double d)
{
if(d<0) return effs.at(0);
if(currentSimTime<d) updateTo(d);
if(tees.back()==d) return effs.back();
else
{
//track back along tees until find first t <d
vector<double>::reverse_iterator itTee=tees.rbegin();
vector<rab::vector3D>::reverse_iterator itF=effs.rbegin();
while(*itTee>d && itTee<(tees.rend()-1))
{
++itTee;
++itF;
}
//use iteration equation to find eff at d
double tempStep=d-*itTee;
if(tempStep<0) cout<<"Warning evaluate call made with out of range parameter"<<endl;
return *itF +tempStep*RHS(*itF,*itTee);
}
}
void rab::Euler::step()
{
effs.push_back(effs.back()+stepLength*RHS(effs.back(),tees.back()));
currentSimTime+=stepLength;
tees.push_back(currentSimTime);
//if the vectors are too long remove half of the data
if(effs.size()>MAXRECORDS)
{
int removed=MAXRECORDS/2;
vector<rab::vector3D>::const_iterator it=effs.begin();
vector<rab::vector3D>::const_iterator it1=it;
it1+=removed;
effs.erase(it,it1);
vector<double>::const_iterator it3=tees.begin();
vector<double>::const_iterator it4=it3;
it4+=removed;
tees.erase(it3,it4);
}
//cout<<"Updating euler step "<<currentSimTime<<endl;//debug line
}
rab::vector3D rab::Euler::getCurrentFValue()
{
return effs.back();
}
rab::MotionSolver::MotionSolver()
{
}
rab::MotionSolver::MotionSolver(rab::vector3D pos,rab::vector3D vel ,Euler* pE)
{
pVelSol=pE;
pVelSol->setStartEff(vel);
setStartEff(pos);
}
void rab::MotionSolver::setStepLength(double step)
{
stepLength=step;
pVelSol->setStepLength(step);
}
rab::vector3D rab::MotionSolver::RHS(rab::vector3D v,double d)
{
return pVelSol->evaluateAt(d);
}
rab::vector3D rab::MotionSolver::getVelocityAt(double d)
{
return pVelSol->evaluateAt(d);
}
rab::vector3D rab::MotionSolver::getCurrentVelocity()
{
return pVelSol->getCurrentFValue();
}
rab::vector3D rab::MotionSolver::getCurrentPosition()
{
return getCurrentFValue();
}
void rab::MotionSolver::step()
{
effs.push_back(effs.back()+stepLength*(pVelSol->getCurrentFValue()));
currentSimTime+=stepLength;
tees.push_back(currentSimTime);
pVelSol->step();
//if the vectors are too long remove half of the data
if(effs.size()>MAXRECORDS)
{
int removed=MAXRECORDS/2;
vector<rab::vector3D>::const_iterator it=effs.begin();
vector<rab::vector3D>::const_iterator it1=it;
it1+=removed;
effs.erase(it,it1);
vector<double>::const_iterator it3=tees.begin();
vector<double>::const_iterator it4=it3;
it4+=removed;
tees.erase(it3,it4);
}
//cout<<"Updating solver step "<<currentSimTime<<endl;//debug line
}
//-----------------------------------------------------------------------------------
//implementation of user defined classes below here
rab::vector3D EulerSimple::RHS(rab::vector3D v,double t)
{
return -1*v;
}
//the EulerWindBullet class methods------------------------
void EulerWindBullet::setBulletMass(double m){bulletMass=m;}
void EulerWindBullet::setARcoeff(double coeff){ARcoeff=coeff;}
void EulerWindBullet::setWRcoeff(double coeff){WRcoeff=coeff;}
void EulerWindBullet::setVeePow(double pow){veePow=pow;}
void EulerWindBullet::setWindVel(rab::vector3D vel){windVel=vel;}
//you must write the next method - it has a holding function supplied
//to allow the code to compile
rab::vector3D EulerWindBullet::RHS(rab::vector3D v,double t)
{
double mass = bulletMass;
double gravity = 10;
double x = ( 1.F/mass ) * ( windVel.getX() * WRcoeff ) - (ARcoeff* v.getX());
double y = ( 1.F/mass ) * ( windVel.getY() * WRcoeff ) - (ARcoeff* v.getY());
double z = ( 1.F/mass ) * ( windVel.getZ() * WRcoeff ) - (ARcoeff* v.getZ());
return rab::vector3D( x, y-gravity, z);
}