00001
00002
00004
00005 #include "MixedReactionMover.h"
00006
00008
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
00032
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
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
00048 m_iCount = (int) xInitial;
00049 double minRatio;
00050 double trialEndTime = xFinal;
00051
00052 double *tempChem = new double[nChem];
00053
00054
00055 Notify();
00056 nextTime += 1.0;
00057
00058 while(m_dTime < xFinal)
00059 {
00060
00061 double R = m_pRNG->uniform();
00062
00063 double gammaS = m_pMixedReactionNetwork->GetTotalStochasticReactionProbability();
00064 while(gammaS == 0.0 && m_dTime < nextTime)
00065 {
00066
00067 cout << "GammaS = " << gammaS << endl;
00068 cin.get();
00069
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
00080 cout << "Trial end time = " << trialEndTime << endl;
00081
00082
00083
00084 m_pODEMover->Move(m_dTime,trialEndTime,m_pReactionNetwork);
00085 m_pODEMover->ResetStepSize();
00086
00087 gammaS = m_pMixedReactionNetwork->GetTotalStochasticReactionProbability();
00088
00089 cout << "New GammaS = " << gammaS << endl;
00090 double deltaR = 0.5*gammaS*(trialEndTime - m_dTime);
00091
00092
00093 cout << "DeltaR = " << deltaR << ", R*tol = " << R*m_dAbsTol << endl;
00094 R = R - deltaR;
00095
00096 cout << "New R = " << R << endl;
00097
00098 if(R < 0) {cout << "R = " << R << ", Integrator might fail . . ." << endl;}
00099 m_dTime = trialEndTime;
00100 }
00101 if(gammaS > 0.0)
00102 {
00103
00104
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
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
00120 this->DoStochasticMove(R);
00121 }
00122 else
00123 {
00124
00125 for(int i = 0; i < nChem; i++)
00126 {
00127 m_pReactionNetwork->GetChemical(i)->SetAmount(tempChem[i]);
00128 }
00129
00130
00131 m_pODEMover->Move(m_dTime,nextTime,m_pMixedReactionNetwork);
00132 m_pODEMover->ResetStepSize();
00133 m_dTime = nextTime;
00134
00135
00136 cout << "Taking data at time " << m_dTime << endl;
00137 m_iCount++;
00138 Notify();
00139 nextTime += 1.0;
00140 }
00141 }
00142 else
00143 {
00144
00145 cout << "Taking data at time " << m_dTime << endl;
00146 m_iCount++;
00147 Notify();
00148 nextTime += 1.0;
00149 }
00150
00151 }
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
00169 rxnChannelRateSum[0] = 0.0;
00170
00171
00172 std::vector<double> *pRxnRates = m_pMixedReactionNetwork->GetStochasticReactionRates();
00173
00174
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
00183 double rxnChannelProb = dRand*totalRxnProb;
00184
00185 int chosen = 0;
00186 while ((chosen < (nReactions - 1)) && (rxnChannelProb > rxnChannelRateSum[chosen+1]))
00187 {
00188 chosen++;
00189 }
00190
00191
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
00201 delete [] rxnChannelRate;
00202 delete [] rxnChannelRateSum;
00203 return;
00204 }
00205 }
00206 m_pMixedReactionNetwork->GetStochasticReaction(chosen)->DoReactionOnce();
00207
00208 delete [] rxnChannelRate;
00209 delete [] rxnChannelRateSum;
00210 }