/*************************************************************************/
/********** ChanTAUrk4.cpp *************/
/*************************************************************************/
/**** ****/
/**** Methods for the class Stepmaster ****/
/**** commands initialisation and steps of attached Steppers ****/
/**** ****/
/*************************************************************************/
#include "StepmstrRk4.h"
#include "StepperRk4.h"
// global Stepmaster:
Stepmaster gStepmaster;
Stepmaster::Stepmaster() // constructor
{
itsListHead = itsListTail = 0;
itsCurIdx = 0;
}
Stepmaster::~Stepmaster() // destructor
{
// destroy all attached Steppers before we die
StepperNode *nextNode, *curNode;
for (curNode = itsListHead; curNode; curNode = nextNode) {
nextNode = curNode->itsNext;
delete curNode;
}
// now we can die peacefully
}
void Stepmaster::Attach( Stepper& pStepper)
{
// first, if the Stepper is already attached to another Stepmaster,
// then remove it
if (pStepper.itsMaster) pStepper.itsMaster->Remove( pStepper );
// now add the given stepper to the tail of the list
StepperNode *node = new StepperNode( itsListTail, pStepper );
itsListTail = node;
if (!itsListHead) itsListHead = node;
// and set its pointer to point to us
pStepper.itsMaster = this;
}
void Stepmaster::doStepinit(const real dt )
{
// call the Stepinit method for all attached Steppers
for (StepperNode *node=itsListHead; node; node = node->itsNext) {
node->itsStepper->Init(dt);
}
}
/* General step function. The only one that update the time */
void Stepmaster::StepAll( const real dt )
{
// call the Step(dt) method for all attached Steppers
for (StepperNode *node=itsListHead; node; node = node->itsNext) {
node->itsStepper->Step(dt);
}
// now update itsCurIdx
itsCurIdx = !itsCurIdx;
}
/* Runge Kutta step functions : one for each step of the method */
void Stepmaster::doStepk1( const real dt )
{
// call the Stepk1(dt) method for all attached Steppers
for (StepperNode *node=itsListHead; node; node = node->itsNext) {
node->itsStepper->Stepk1(dt);
}
}
void Stepmaster::doStepk2( const real dt )
{
// call the Stepk2(dt) method for all attached Steppers
for (StepperNode *node=itsListHead; node; node = node->itsNext) {
node->itsStepper->Stepk2(dt);
}
}
void Stepmaster::doStepk3( const real dt )
{
// call the Stepk3(dt) method for all attached Steppers
for (StepperNode *node=itsListHead; node; node = node->itsNext) {
node->itsStepper->Stepk3(dt);
}
}
void Stepmaster::doStepk4( const real dt )
{
// call the Stepk4(dt) method for all attached Steppers
for (StepperNode *node=itsListHead; node; node = node->itsNext) {
node->itsStepper->Stepk4(dt);
}
}
void Stepmaster::Remove( Stepper& pStepper )
{
// the given Stepper is either dying or attaching to another master
// so remove it from our list, and update its pointer
StepperNode *curNode, *lastNode=0;
for (curNode = itsListHead; curNode;
lastNode = curNode, curNode = curNode->itsNext) {
if ( curNode->itsStepper == &pStepper ) {
// found it! now remove it from the list
if (lastNode) lastNode->itsNext = curNode->itsNext;
if (curNode==itsListHead) itsListHead = curNode->itsNext;
if (curNode==itsListTail) itsListTail = lastNode;
delete curNode;
pStepper.itsMaster = 0;
return;
}
}
// if we get to this point, it means we didn't find the given Stepper
// this should never happen -- if you want to throw an exception,
// do it here
}