// virtual
C_FLOAT64 CTrajectoryMethodDsaLsodar::doSingleStep(C_FLOAT64 curTime, C_FLOAT64 endTime)
{
  C_FLOAT64 DeltaT = 0.0;
  bool FireReaction = false;

  // if there are stochastic reactions
  if (mPartition.mHasStochastic) // there is at least one stochastic reaction
    {
      if (mNextReactionIndex == C_INVALID_INDEX)
        {
          if (mA0 != 0)
            {
              mNextReactionTime = curTime - log(mpRandomGenerator->getRandomOO()) / mA0;

              // We are sure that we have at least 1 reaction
              mNextReactionIndex = 0;

              C_FLOAT64 sum = 0.0;
              C_FLOAT64 rand = mpRandomGenerator->getRandomOO() * mA0;

              C_FLOAT64 * pAmu = mAmu.array();
              C_FLOAT64 * endAmu = pAmu + mNumReactions;
              const CMathReaction **ppStochastic = mPartition.mStochasticReactions.array();

              // Only consider stochastic reactions
              for (; (sum <= rand) && (pAmu != endAmu); ++pAmu, ++mNextReactionIndex, ++ppStochastic)
                {
                  if (*ppStochastic != NULL)
                    {
                      sum += *pAmu;
                    }
                }

              assert(mNextReactionIndex > 0);

              mNextReactionIndex--;
            }
          else
            {
              mNextReactionTime = std::numeric_limits< C_FLOAT64 >::infinity();
              mNextReactionIndex = C_INVALID_INDEX;
            }
        }

      if (mNextReactionTime <= endTime)
        {
          FireReaction = true;
          DeltaT = mNextReactionTime - curTime;
        }
      else
        {
          DeltaT = std::min(*mpPartitioningSteps, endTime - curTime);
        }
    }
  else
    {
      DeltaT = std::min(*mpPartitioningSteps, endTime - curTime);
    }

  // Even if all reactions are treated stochastically we need to integrate the
  // deterministic system to find time dependent events.
  integrateDeterministicPart(DeltaT);

  if (mStatus == CTrajectoryMethod::NORMAL)
    {
      if (FireReaction)
        {
          fireReaction(mNextReactionIndex);
        }

      if (mStepsAfterPartitionSystem >= *mpPartitioningInterval)
        {
          if (mPartition.rePartition(mContainerState))
            {
              stateChange(CMath::eStateChange::ContinuousSimulation);
            }

          mStepsAfterPartitionSystem = 0;
        }
    }

  ++mStepsAfterPartitionSystem;

  return DeltaT;
}
Esempio n. 2
0
/**
 *  Simulates the system over the next interval of time. The new time after
 *  this step is returned.
 *
 *  @param  currentTime A C_FLOAT64 specifying the current time
 *  @param  endTime A C_FLOAT64 specifying the endTime of the current step()
 *  @return A C_FLOAT giving the new time
 */
C_FLOAT64 CHybridMethod::doSingleStep(C_FLOAT64 currentTime, C_FLOAT64 endTime)
{
  size_t rIndex = 0;
  C_FLOAT64 ds = endTime;

  // if there are stochastic reactions
  if (mPQ.size() != 0) // there is at least one stochastic reaction
    {
      getStochTimeAndIndex(ds, rIndex);

      if (ds <= endTime) // ds is an absolute time value!
        {
          // if there are deterministic reactions
          if (mFirstReactionFlag != NULL) // there is at least one deterministic reaction
            {
              integrateDeterministicPart(ds - currentTime);
            }

          mReactions[rIndex].fire();
          *mpContainerStateTime = ds;
          stateChange(CMath::State);

          if (++mStepsAfterPartitionSystem >= mPartitioningInterval)
            {
              partitionSystem();
              mStepsAfterPartitionSystem = 0;
            }

          updatePriorityQueue(rIndex, ds);
        }
      else
        {
          ds = endTime;

          // if there are deterministic reactions
          if (mFirstReactionFlag != NULL) // there is at least one deterministic reaction
            {
              integrateDeterministicPart(ds - currentTime);
            }

          *mpContainerStateTime = ds;

          if (++mStepsAfterPartitionSystem >= mPartitioningInterval)
            {
              partitionSystem();
              mStepsAfterPartitionSystem = 0;
            }

          updatePriorityQueue(C_INVALID_INDEX, endTime);
        }
    }
  else // there is no stochastic reaction
    {
      // if there are deterministic reactions
      if (mFirstReactionFlag != NULL) // there is at least one deterministic reaction
        {
          integrateDeterministicPart(ds - currentTime);
        }

      *mpContainerStateTime = ds;

      if (++mStepsAfterPartitionSystem >= mPartitioningInterval)
        {
          partitionSystem();
          mStepsAfterPartitionSystem = 0;
        }

      updatePriorityQueue(C_INVALID_INDEX, ds);
    }

  return ds;
}