00001 // ContinuousTimeMonteCarloMover.cpp: implementation of the ContinuousTimeMonteCarloMover class. 00002 // 00004 00005 #include "ContinuousTimeMonteCarloMover.h" 00006 00008 // Construction/Destruction 00010 00011 CContinuousTimeMonteCarloMover::CContinuousTimeMonteCarloMover() 00012 { 00013 00014 } 00015 00016 CContinuousTimeMonteCarloMover::CContinuousTimeMonteCarloMover(int seed, double frequency) 00017 :CReactionMover(seed, frequency) 00018 { 00019 m_pRNG = new Rand(); 00020 m_pRNG->seed(seed); 00021 } 00022 00023 CContinuousTimeMonteCarloMover::~CContinuousTimeMonteCarloMover() 00024 { 00025 delete m_pRNG; 00026 } 00027 00028 void CContinuousTimeMonteCarloMover::Move(double xInitial, double xFinal, ReactionNetwork *pReactionNetwork) 00029 { 00030 if(this->MoveTimeIsZero(xFinal-xInitial)) {return;} 00031 00032 // set the member pointer to the local pointer that is passed in 00033 m_pReactionNetwork = pReactionNetwork; 00034 m_dTime = xInitial; 00035 m_iCount = (int) xInitial; 00036 double nextTime = m_dTime; 00037 00038 double rand1, rand2; 00039 double dcount = 0.0, scount = 0.0; 00040 double timeIncrement = 0.0; 00041 00042 m_iCount++; 00043 Notify(); 00044 nextTime += 1.0; 00045 00046 while(m_dTime < xFinal) 00047 { 00048 // Choose a move and get the time it will take 00049 rand1 = m_pRNG->uniform(); 00050 rand2 = m_pRNG->uniform(); 00051 timeIncrement = this->ChooseMove(rand1,rand2); 00052 m_dTime += timeIncrement; 00053 00054 // if the next move carries over the current data taking time, 00055 // take the data first then do the move 00056 if( m_dTime >= nextTime) 00057 { 00058 // notify 00059 m_iCount++; 00060 Notify(); 00061 nextTime += 1.0; 00062 } 00063 00064 // perform the currently selected move 00065 this->DoMove(); 00066 00067 } 00068 } 00069 00070 // ChooseMove() should be rewritten to make more sense! 00071 00072 double CContinuousTimeMonteCarloMover::ChooseMove(double rand1, double rand2) 00073 { 00074 double totalReactionProbability = 0.0; 00075 int nReactions = m_pReactionNetwork->GetNumberOfReactions(); 00076 00077 double *reactionChannelRate = new double[nReactions]; 00078 double *reactionChannelRateSum = new double[nReactions+1]; 00079 00080 // reactionChannelRateSum gives sum up to but not including i 00081 reactionChannelRateSum[0] = 0.0; 00082 00083 // get a copy of the reaction rates 00084 std::vector<double> *reactionRates = m_pReactionNetwork->GetReactionRates(); 00085 00086 // compute reaction channel rate sums 00087 for (int i = 0; i < nReactions; i++) 00088 { 00089 reactionChannelRate[i] = reactionRates->at(i); 00090 reactionChannelRateSum[i+1] = reactionChannelRateSum[i] + reactionChannelRate[i]; 00091 totalReactionProbability += reactionChannelRate[i]; 00092 } 00093 00094 // choose reaction channel and time to next reaction 00095 double reactionChannelProbability = rand1*totalReactionProbability; 00096 // avoid division by zero error 00097 if(rand2 == 0.0 ) rand2 = 1.0; 00098 double timeToNextReaction=(1.0/totalReactionProbability)*log(1.0/rand2); 00099 00100 int channelChosen = 0; 00101 while ((channelChosen < (nReactions - 1)) 00102 && (reactionChannelProbability > reactionChannelRateSum[channelChosen+1])) 00103 { 00104 channelChosen++; 00105 } 00106 00107 // set the correct reaction channel 00108 m_dChannelChosen = channelChosen; 00109 00110 // free memory 00111 00112 delete [] reactionChannelRate; 00113 delete [] reactionChannelRateSum; 00114 00115 return timeToNextReaction; 00116 } 00117 00118 void CContinuousTimeMonteCarloMover::DoMove() 00119 { 00120 m_pReactionNetwork->GetReaction(m_dChannelChosen)->DoReactionOnce(); 00121 }