Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

MixedReactionMover.cpp

Go to the documentation of this file.
00001 // MixedReactionMover.cpp: implementation of the CMixedReactionMover class.
00002 //
00004 
00005 #include "MixedReactionMover.h"
00006 
00008 // Construction/Destruction
00010 
00011 CMixedReactionMover::CMixedReactionMover()
00012 {
00013 
00014 }
00015 
00016 CMixedReactionMover::CMixedReactionMover(int seed, CDifferentialEquationMover *pODEMover, double absTol)
00017 :CReactionMover(seed,1.0)
00018 {
00019         m_pODEMover = pODEMover;
00020         m_pRNG = new Rand(seed);
00021         m_dAbsTol = absTol;
00022 }
00023 
00024 CMixedReactionMover::~CMixedReactionMover()
00025 {
00026         delete m_pRNG;
00027 }
00028 
00029 void CMixedReactionMover::Move(double xInitial, double xFinal, ReactionNetwork *pReactionNetwork)
00030 {
00031         // downcast to a CMixedReactionNetwork and make sure it is one - you shouldn't
00032         // pass a non-mixed RN into this mover anyway!
00033         m_pReactionNetwork = pReactionNetwork;
00034         m_pMixedReactionNetwork = dynamic_cast<CMixedReactionNetwork *>(pReactionNetwork);
00035         if(0 == m_pReactionNetwork)
00036         {
00037                 throw std::runtime_error("Reaction Network is not a mixed network!");
00038         }
00039         // bind the MixedNetwork to the TauNetwork
00040         m_pTauNetwork = new CTauNetwork(m_pMixedReactionNetwork);
00041 
00042         
00043         int nChem = m_pMixedReactionNetwork->GetNumberOfChemicals();
00044         int nRates = m_pMixedReactionNetwork->GetNumberOfReactions();
00045         m_dTime = xInitial;
00046         double nextTime = m_dTime;
00047         // may be unsafe if xInitial has a fractional part!
00048         m_iCount = (int) xInitial;
00049         double minRatio;
00050         double trialEndTime = xFinal;
00051 
00052         double *tempChem = new double[nChem];
00053 
00054         // Notify observers at initial time (usually 0)
00055         Notify();
00056         nextTime += 1.0;
00057 
00058         while(m_dTime < xFinal)
00059         {
00060                 // pick a random number
00061                 double R = m_pRNG->uniform();
00062                 // compute total stochastic reaction probability
00063                 double gammaS = m_pMixedReactionNetwork->GetTotalStochasticReactionProbability();
00064                 while(gammaS == 0.0 && m_dTime < nextTime)
00065                 {
00066                         // XXX debug
00067                         cout << "GammaS = " << gammaS << endl;
00068                         cin.get();
00069                         // compute the putative integration endpoint
00070                         minRatio = 10000000;
00071                         for(int i = 0; i < nRates; i++)
00072                         {
00073                                 double rate = m_pMixedReactionNetwork->GetReaction(i)->GetRate();
00074                                 double tempRatio = m_dAbsTol/rate;
00075                                 minRatio = __min(tempRatio,minRatio);
00076                         }
00077                         trialEndTime = __min(m_dTime + m_pODEMover->GetStepSize(), nextTime);
00078                         trialEndTime = __min(trialEndTime,m_dTime + minRatio);
00079                         // XXX debug
00080                         cout << "Trial end time = " << trialEndTime << endl;
00081                         // now run for this amount of time on the REAL network (all stochastic
00082                         // reactions have zero rate so there is no danger of the stochastic 
00083                         // rates changing anything)
00084                         m_pODEMover->Move(m_dTime,trialEndTime,m_pReactionNetwork);
00085                         m_pODEMover->ResetStepSize();
00086                         // now recompute R
00087                         gammaS = m_pMixedReactionNetwork->GetTotalStochasticReactionProbability();
00088                         // XXX debug
00089                         cout << "New GammaS = " << gammaS << endl;
00090                         double deltaR = 0.5*gammaS*(trialEndTime - m_dTime);
00091                         // do I need to repeat this until we're below the tolerance?
00092                         // XXX debug
00093                         cout << "DeltaR = " << deltaR << ", R*tol = " << R*m_dAbsTol << endl;
00094                         R = R - deltaR;
00095                         // XXX debug
00096                         cout << "New R = " << R << endl;
00097                         // XXX debug
00098                         if(R < 0) {cout << "R = " << R << ", Integrator might fail . . ." << endl;}
00099                         m_dTime = trialEndTime;
00100                 } // end "gammaS == 0.0" while loop
00101                 if(gammaS > 0.0)
00102                 {
00103                         // call the tau network from 0 to R, get tOfTau at end.  Save current 
00104                         // chemical concentrations first.
00105                         for(int i = 0; i < nChem; i++)
00106                         {
00107                                 tempChem[i] = m_pReactionNetwork->GetChemical(i)->GetAmount();
00108                         }
00109                         double deltaT = m_pODEMover->GetStepSize();
00110                         m_pODEMover->SetStepSize(gammaS*deltaT);
00111                         m_pODEMover->Move(0,R,m_pTauNetwork);
00112                         m_pODEMover->ResetStepSize();
00113                         // get the amount of time that elapsed
00114                         double tOfTau = m_pTauNetwork->GetTOfTau();
00115                         cout << "Tau network integrated, time elapsed = " << tOfTau << endl;
00116                         if(m_dTime + tOfTau < nextTime)
00117                         {
00118                                 m_dTime += tOfTau;
00119                                 // pick a stochastic move and if OK do it
00120                                 this->DoStochasticMove(R);
00121                         }
00122                         else  // inefficient if nextTime << 1/gammaS
00123                         {
00124                                 // restore old chemical concentrations before move
00125                                 for(int i = 0; i < nChem; i++)
00126                                 {
00127                                         m_pReactionNetwork->GetChemical(i)->SetAmount(tempChem[i]);
00128                                 }
00129                                 // run on REAL MIXED network (don't want to integrate 
00130                                 // stochastic reactions)
00131                                 m_pODEMover->Move(m_dTime,nextTime,m_pMixedReactionNetwork);
00132                                 m_pODEMover->ResetStepSize();
00133                                 m_dTime = nextTime;
00134                                 // take data
00135                                 // XXX debug
00136                                 cout << "Taking data at time " << m_dTime << endl;
00137                                 m_iCount++;
00138                                 Notify();
00139                                 nextTime += 1.0;
00140                         }
00141                 }
00142                 else
00143                 {
00144                         // XXX debug
00145                         cout << "Taking data at time " << m_dTime << endl;
00146                         m_iCount++;
00147                         Notify();
00148                         nextTime += 1.0;
00149                 }
00150         
00151         } // end "while(time < finalTime)" loop
00152 
00153         delete [] tempChem;
00154         delete m_pTauNetwork;
00155 
00156         return;
00157 }
00158 
00159 void CMixedReactionMover::DoStochasticMove(double dRand)
00160 {
00161         int i;
00162         double totalRxnProb = 0.0;
00163         int nReactions = m_pMixedReactionNetwork->GetNumberOfStochasticReactions();
00164         
00165         double *rxnChannelRate = new double[nReactions];
00166         double *rxnChannelRateSum = new double[nReactions+1];
00167 
00168         // rxnChannelRateSum gives sum up to but not including i
00169         rxnChannelRateSum[0] = 0.0;
00170         
00171         // get a copy of the stochastic reaction rates 
00172         std::vector<double> *pRxnRates = m_pMixedReactionNetwork->GetStochasticReactionRates();
00173 
00174         // compute reaction channel rate sums
00175         for (i = 0; i < nReactions; i++)
00176         {
00177                 rxnChannelRate[i] = pRxnRates->at(i);
00178                 rxnChannelRateSum[i+1] = rxnChannelRateSum[i] + rxnChannelRate[i];
00179                 totalRxnProb += rxnChannelRate[i];
00180         }
00181 
00182         // choose reaction channel
00183         double rxnChannelProb = dRand*totalRxnProb;
00184         
00185         int chosen = 0;
00186         while ((chosen < (nReactions - 1)) && (rxnChannelProb > rxnChannelRateSum[chosen+1])) 
00187         {
00188                 chosen++;
00189         }
00190         // if the reaction would change the chemical by an amount less than that present
00191         // do not do the reaction; otherwise it's OK
00192         std::vector<Chemical *> *pRxnChem = m_pMixedReactionNetwork->GetStochasticReaction(chosen)->GetChemicals();
00193         for(i = 0; i < pRxnChem->size(); i++)
00194         {
00195                 int whichChem = pRxnChem->at(i)->GetChemicalNumber();
00196                 double currAmount = pRxnChem->at(i)->GetAmount();
00197                 double deltaAmount = m_pMixedReactionNetwork->GetStochasticReaction(chosen)->GetNumberChangedByReaction(whichChem);
00198                 if(currAmount + deltaAmount < 0.0)
00199                 {
00200                         // fail the reaction and return
00201                         delete [] rxnChannelRate;
00202                         delete [] rxnChannelRateSum;
00203                         return;
00204                 }
00205         }
00206         m_pMixedReactionNetwork->GetStochasticReaction(chosen)->DoReactionOnce();
00207 
00208         delete [] rxnChannelRate;
00209         delete [] rxnChannelRateSum;
00210 }

Generated on Mon Nov 3 09:38:01 2003 by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002