/** * Simulates the system over the next interval of time. The timestep * is given as argument. * * @param ds A C_FLOAT64 specifying the timestep */ C_FLOAT64 CTauLeapMethod::doSingleStep(C_FLOAT64 ds) { C_FLOAT64 Lambda, Tmp, Tau, Tau1, Tau2; updatePropensities(); mAvgDX = 0.0; mSigDX = 0.0; CMathReaction * pReaction = mReactions.array(); const C_FLOAT64 * pAmu = mAmu.array(); const C_FLOAT64 * pAmuEnd = pAmu + mNumReactions; const C_FLOAT64 * pFirstSpecies = mContainerState.array() + mFirstReactionSpeciesIndex; for (; pAmu != pAmuEnd; ++pAmu, ++pReaction) { const CMathReaction::Balance & Balance = pReaction->getNumberBalance(); const CMathReaction::SpeciesBalance * it = Balance.array(); const CMathReaction::SpeciesBalance * end = it + Balance.size(); for (; it != end; ++it) { mAvgDX[it->first - pFirstSpecies] += it->second **pAmu; mSigDX[it->first - pFirstSpecies] += it->second * it->second **pAmu; } } Tau1 = Tau2 = std::numeric_limits< C_FLOAT64 >::infinity(); const C_FLOAT64 * pSpecies = mContainerState.array() + mFirstReactionSpeciesIndex; const C_FLOAT64 * pSpeciesEnd = pSpecies + mNumReactionSpecies; C_FLOAT64 * pAvgDX = mAvgDX.array(); C_FLOAT64 * pSigDX = mSigDX.array(); for (; pSpecies != pSpeciesEnd; ++pSpecies, ++pAvgDX, ++pSigDX) { if ((Tmp = mEpsilon * fabs(*pSpecies)) < 1.0) Tmp = 1.0; *pAvgDX = Tmp / fabs(*pAvgDX); *pSigDX = (Tmp * Tmp) / fabs(*pSigDX); if (Tau1 > *pAvgDX) Tau1 = *pAvgDX; if (Tau2 > *pSigDX) Tau2 = *pSigDX; } Tau = std::min(Tau1, Tau2); if (ds < Tau) Tau = ds; pAmu = mAmu.array(); C_FLOAT64 * pK = mK.array(); C_FLOAT64 * pKEnd = pK + mNumReactions; for (; pAmu != pAmuEnd; ++pAmu, ++pK) { Lambda = *pAmu * Tau; if (Lambda < 0.0) CCopasiMessage(CCopasiMessage::EXCEPTION, MCTrajectoryMethod + 10); else if (Lambda > 2.0e9) CCopasiMessage(CCopasiMessage::EXCEPTION, MCTrajectoryMethod + 26); *pK = mpRandomGenerator->getRandomPoisson(Lambda); } while (!updateSystem()) { Tau *= 0.5; pK = mK.array(); for (; pK != pKEnd; ++pK) { *pK *= 0.5; if (*pK < floor(*pK + 0.75)) { *pK += mpRandomGenerator->getRandomCC() < 0.5 ? - 0.5 : 0.5; } } } return Tau; }
/** * Simulates the system over the next interval of time. The timestep * is given as argument. * * @param ds A C_FLOAT64 specifying the timestep */ C_FLOAT64 CTauLeapMethod::doSingleStep(C_FLOAT64 ds) { C_FLOAT64 Lambda, Tmp, Tau, Tau1, Tau2; updatePropensities(); mAvgDX = 0.0; mSigDX = 0.0; std::vector< CReactionDependencies >::const_iterator itReaction = mReactionDependencies.begin(); const C_FLOAT64 * pAmu = mAmu.array(); const C_FLOAT64 * pAmuEnd = pAmu + mNumReactions; for (; pAmu != pAmuEnd; ++pAmu, ++itReaction) { const C_FLOAT64 * pMultiplicity = itReaction->mSpeciesMultiplier.array(); const C_FLOAT64 * pMultiplicityEnd = pMultiplicity + itReaction->mSpeciesMultiplier.size(); const size_t * pIndex = itReaction->mMethodSpeciesIndex.array(); for (; pMultiplicity != pMultiplicityEnd; ++pMultiplicity, ++pIndex) { mAvgDX[*pIndex] += *pMultiplicity * *pAmu; mSigDX[*pIndex] += *pMultiplicity * *pMultiplicity * *pAmu; } } Tau1 = Tau2 = std::numeric_limits< C_FLOAT64 >::infinity(); const C_FLOAT64 * pNumber = mMethodState.beginIndependent() + mFirstReactionSpeciesIndex - 1; const C_FLOAT64 * pNumberEnd = pNumber + mNumReactionSpecies; C_FLOAT64 * pAvgDX = mAvgDX.array(); C_FLOAT64 * pSigDX = mSigDX.array(); for (; pNumber != pNumberEnd; ++pNumber, ++pAvgDX, ++pSigDX) { if ((Tmp = mEpsilon * fabs(*pNumber)) < 1.0) Tmp = 1.0; *pAvgDX = Tmp / fabs(*pAvgDX); *pSigDX = (Tmp * Tmp) / fabs(*pSigDX); if (Tau1 > *pAvgDX) Tau1 = *pAvgDX; if (Tau2 > *pSigDX) Tau2 = *pSigDX; } Tau = std::min(Tau1, Tau2); if (ds < Tau) Tau = ds; pAmu = mAmu.array(); C_FLOAT64 * pK = mK.array(); C_FLOAT64 * pKEnd = pK + mNumReactions; for (; pAmu != pAmuEnd; ++pAmu, ++pK) { Lambda = *pAmu * Tau; if (Lambda < 0.0) CCopasiMessage(CCopasiMessage::EXCEPTION, MCTrajectoryMethod + 10); else if (Lambda > 2.0e9) CCopasiMessage(CCopasiMessage::EXCEPTION, MCTrajectoryMethod + 26); *pK = mpRandomGenerator->getRandomPoisson(Lambda); } while (!updateSystem()) { Tau *= 0.5; pK = mK.array(); for (; pK != pKEnd; ++pK) { *pK *= 0.5; if (*pK < floor(*pK + 0.75)) { *pK += mpRandomGenerator->getRandomCC() < 0.5 ? - 0.5 : 0.5; } } } return Tau; }