#ifndef Numerica_ODECrawler_H
#define Numerica_ODECrawler_H
#include <TVectorD.h>
#include <Glasses/ZGlass.h>
class ODECrawlerMaster
{
public:
virtual ~ODECrawlerMaster() {}
virtual UInt_t ODEOrder() = 0;
virtual void ODEDerivatives(const Double_t x, const TVectorD& y, TVectorD& d) = 0;
virtual void ODEStart(TVectorD& v, Double_t& x1, Double_t& x2) = 0;
ClassDef(ODECrawlerMaster, 1);
};
class ODEStorage
{
protected:
Int_t mOrder;
Int_t mSize;
public:
ODEStorage() :
mOrder(0), mSize(0) {}
ODEStorage(Int_t order, Int_t capacity=128) :
mOrder(order), mSize(0) {}
virtual ~ODEStorage() {}
Int_t Order() const { return mOrder; }
Int_t Size() const { return mSize; }
void ResetOrder(Int_t order, Int_t capacity=-1)
{
mOrder = order;
if (capacity == -1)
capacity = 12*mSize/10;
Reset(capacity);
}
void Reset()
{
Reset(12*mSize/10);
}
virtual void Reset(Int_t capacity) = 0;
virtual void AddEntry(Double_t x, Double_t* y) = 0;
virtual Double_t GetMinXStored() const = 0;
virtual Double_t GetMaxXStored() const = 0;
virtual Double_t GetDeltaXStored() const { return GetMaxXStored() - GetMinXStored(); }
ClassDef(ODEStorage, 1);
};
template<typename TT>
class ODEStorageT : public ODEStorage
{
protected:
vector<TT> mX;
vector<TT> mY;
public:
ODEStorageT(Int_t order, Int_t capacity=128) :
ODEStorage(order, capacity)
{
mX.reserve(capacity);
mY.reserve(mOrder*capacity);
}
virtual ~ODEStorageT() {}
virtual void Reset(Int_t capacity)
{
vector<TT> x; x.reserve(capacity); mX.swap(x);
vector<TT> y; y.reserve(mOrder*capacity); mY.swap(y);
mSize = 0;
}
virtual void AddEntry(Double_t x, Double_t* y)
{
mX.push_back(x);
for (Int_t i = 0; i < mOrder; ++i)
mY.push_back(y[i]);
++mSize;
}
virtual Double_t GetMinXStored() const { return mSize > 0 ? mX[0] : 0; }
virtual Double_t GetMaxXStored() const { return mSize > 0 ? mX[mSize-1] : 0; }
virtual Double_t GetDeltaXStored() const { return mSize > 0 ? mX[mSize-1] - mX[0] : 0; }
TT GetX(Int_t i) const { return mX[i]; }
const TT* GetY(Int_t i) const { return &mY[mOrder*i]; }
const TT* GetXArr() const { return &mX[0]; }
const TT* GetYArr() const { return &mY[0]; }
void AssignY(Int_t i, TVectorT<TT>& v) const { v.Use(mOrder, &mY[mOrder*i]); }
ClassDef(ODEStorageT, 1);
};
#ifndef __APPLE__
template class ODEStorageT<Float_t>;
template class ODEStorageT<Double_t>;
#endif
typedef ODEStorageT<Float_t> ODEStorageF;
typedef ODEStorageT<Double_t> ODEStorageD;
class ODECrawler : public ZGlass
{
private:
Double_t hTINY, hSAFETY, hPGROW, hPSHRNK, hERRCON;
ODECrawlerMaster *hTrueMaster;
Bool_t hCrawling;
void _init();
protected:
ZLink<ZGlass> mODEMaster;
Int_t mGuessesOK;
Int_t mGuessesBad;
Int_t mStored;
Int_t mMaxSteps;
Int_t mStoreMax;
Double_t mStoreDx;
ODEStorage *mStorage;
TVectorD mY;
Int_t mN;
Double_t mAcc;
Double_t mX1;
Double_t mX2;
Double_t mH1;
Double_t mHmin;
void init_integration(Bool_t call_ode_start);
Int_t Rkqs(TVectorD& y, TVectorD& dydx, Double_t& x, Double_t htry,
TVectorD& yscal, Double_t& h_last, Double_t& h_next);
void Rkck(TVectorD& y, TVectorD& dydx, Double_t x, Double_t h,
TVectorD& yout, TVectorD& yerr);
void Integrate();
public:
ODECrawler(const Text_t* n="ODECrawler", const Text_t* t=0) :
ZGlass(n,t) { _init(); }
virtual ~ODECrawler();
void AdvanceXLimits(Double_t delta_x=0);
void SetStorage(ODEStorage* s);
void DetachStorage();
ODEStorage* SwapStorage(ODEStorage* s);
void Crawl(Bool_t call_ode_start=true);
void ChangeOrderInPlace(Int_t order);
Double_t* RawYArray();
#include "ODECrawler.h7"
ClassDef(ODECrawler, 1);
};
#endif