Example #1
0
CTrajectoryMethod::Status CLsodaMethod::step(const double & deltaT)
{
  if (mData.dim == 0 && mNumRoots == 0) //just do nothing if there are no variables
    {
      mTime = mTime + deltaT;
      mMethodState.setTime(mTime);
      *mpCurrentState = mMethodState;

      return NORMAL;
    }

  C_FLOAT64 EndTime = mTime + deltaT;

  if (mTargetTime != EndTime)
    {
      mTargetTime = EndTime;
      mRootCounter = 0;
    }
  else
    {
      mRootCounter++;

      if (mRootCounter > *mpMaxInternalSteps)
        {
          return FAILURE;
        }
    }

  C_INT ITOL = 2; // mRtol scalar, mAtol vector
  C_INT one = 1;
  C_INT DSize = mDWork.size();
  C_INT ISize = mIWork.size();

  if (mRoots.size() > 0)
    {
      mLSODAR(&EvalF, //  1. evaluate F
              &mData.dim, //  2. number of variables
              mY, //  3. the array of current concentrations
              &mTime, //  4. the current time
              &EndTime, //  5. the final time
              &ITOL, //  6. error control
              &mRtol, //  7. relative tolerance array
              mAtol.array(), //  8. absolute tolerance array
              &mState, //  9. output by overshoot & interpolation
              &mLsodaStatus, // 10. the state control variable
              &one, // 11. further options (one)
              mDWork.array(), // 12. the double work array
              &DSize, // 13. the double work array size
              mIWork.array(), // 14. the int work array
              &ISize, // 15. the int work array size
              NULL, // 16. evaluate J (not given)
              &mJType, // 17. type of j evaluation 2 internal full matrix
              &EvalR, // 18. evaluate constraint functions
              &mNumRoots, // 19. number of constraint functions g(i)
              mRoots.array()); // 20. integer array of length NG for output of root information

      switch (mLsodaStatus)
        {
          case -33:

            switch (mRootMasking)
              {
                case NONE:
                case DISCRETE:
                  // Reset the integrator to the state before the failed integration.
                  mMethodState = *mpCurrentState;
                  mTime = mMethodState.getTime();
                  mLsodaStatus = 1;

                  // Create a mask which hides all roots being constant and zero.
                  createRootMask();
                  break;

                case ALL:
                  break;
              }

            break;

          default:

            switch (mRootMasking)
              {
                case NONE:
                case DISCRETE:
                  break;

                case ALL:
                {
                  const bool * pDiscrete = mDiscreteRoots.array();
                  bool * pMask = mRootMask.array();
                  bool * pMaskEnd = pMask + mNumRoots;
                  bool Destroy = true;

                  for (; pMask != pMaskEnd; ++pMask, ++pDiscrete)
                    {
                      if (*pMask)
                        {
                          if (*pDiscrete)
                            {
                              Destroy = false;
                            }
                          else
                            {
                              *pMask = false;
                            }
                        }
                    }

                  if (Destroy)
                    {
                      destroyRootMask();
                    }
                  else
                    {
                      mRootMasking = DISCRETE;
                    }

                  mLsodaStatus = 1;
                }
              }

            break;
        }
    }
  else
    {
      mLSODA(&EvalF, //  1. evaluate F
             &mData.dim, //  2. number of variables
             mY, //  3. the array of current concentrations
             &mTime, //  4. the current time
             &EndTime, //  5. the final time
             &ITOL, //  6. error control
             &mRtol, //  7. relative tolerance array
             mAtol.array(), //  8. absolute tolerance array
             &mState, //  9. output by overshoot & interpolation
             &mLsodaStatus, // 10. the state control variable
             &one, // 11. further options (one)
             mDWork.array(), // 12. the double work array
             &DSize, // 13. the double work array size
             mIWork.array(), // 14. the int work array
             &ISize, // 15. the int work array size
             NULL, // 16. evaluate J (not given)
             &mJType);        // 17. the type of jacobian calculate (2)
    }

  // Why did we ignore this error?
  // if (mLsodaStatus == -1) mLsodaStatus = 2;

  // The status of the integrator.
  Status Status = NORMAL;

  if ((mLsodaStatus <= 0))
    {
      Status = FAILURE;
      CCopasiMessage(CCopasiMessage::EXCEPTION, MCTrajectoryMethod + 6, mErrorMsg.str().c_str());
    }

  // If mLsodaStatus == 3 we have found a root. This needs to be indicated to
  // the caller as it is not sufficient to rely on the fact that T < TOUT

  if (mLsodaStatus == 3)
    {
      // It is sufficient to switch to 2. Eventual state changes due to events
      // are indicated via the method stateChanged()
      mLsodaStatus = 2;
      Status = ROOT;
    }

  mMethodState.setTime(mTime);
  *mpCurrentState = mMethodState;

  return Status;
}
Example #2
0
CTrajectoryMethod::Status CLsodaMethod::step(const double & deltaT)
{
  if (mData.dim == 0 && mNumRoots == 0) //just do nothing if there are no variables
    {
      mTime = mTime + deltaT;
      mMethodState.setTime(mTime);
      *mpCurrentState = mMethodState;

      return NORMAL;
    }

  C_FLOAT64 EndTime = mTime + deltaT;

  if (mTargetTime != EndTime)
    {
      // We have a new end time and reset the root counter.
      mTargetTime = EndTime;
      mRootCounter = 0;
    }
  else
    {
      // We are called with the same end time which means a root has previously been
      // found. We increase the root counter and check whether the limit is reached.
      mRootCounter++;

      if (mRootCounter > *mpMaxInternalSteps)
        {
          return FAILURE;
        }
    }

  C_INT ITOL = 2; // mRtol scalar, mAtol vector
  C_INT one = 1;
  C_INT DSize = (C_INT) mDWork.size();
  C_INT ISize = (C_INT) mIWork.size();

  // The return status of the integrator.
  Status Status = NORMAL;

  if (mRoots.size() > 0)
    {
      mLSODAR(&EvalF, //  1. evaluate F
              &mData.dim, //  2. number of variables
              mY, //  3. the array of current concentrations
              &mTime, //  4. the current time
              &EndTime, //  5. the final time
              &ITOL, //  6. error control
              &mRtol, //  7. relative tolerance array
              mAtol.array(), //  8. absolute tolerance array
              &mState, //  9. output by overshoot & interpolation
              &mLsodaStatus, // 10. the state control variable
              &one, // 11. further options (one)
              mDWork.array(), // 12. the double work array
              &DSize, // 13. the double work array size
              mIWork.array(), // 14. the int work array
              &ISize, // 15. the int work array size
              &EvalJ, // 16. evaluate J (not given)
              &mJType, // 17. type of j evaluation 2 internal full matrix
              &EvalR, // 18. evaluate constraint functions
              &mNumRoots, // 19. number of constraint functions g(i)
              mRoots.array()); // 20. integer array of length NG for output of root information

      // There exist situations where LSODAR reports status = 3, which are actually status = -33
      // Obviously the trivial case is where LSODAR did not advance at all, i.e, the start time
      // equals the current time. It may also happen that a very small steps has been taken in
      // we reset short before we reach the internal step limit.
      if (mLsodaStatus == 3 &&
          (mRootCounter > 0.99 * *mpMaxInternalSteps ||
           mTime == mpCurrentState->getTime()))
        {
          mLsodaStatus = -33;
          mRootCounter = 0;
        }

      switch (mLsodaStatus)
        {
          case -33:

            switch (mRootMasking)
              {
                case NONE:
                case DISCRETE:
                  // Reset the integrator to the state before the failed integration.

                  mMethodState = *mpCurrentState;
                  mTime = mMethodState.getTime();
                  mLsodaStatus = 1;

                  // Create a mask which hides all roots being constant and zero.
                  createRootMask();
                  break;

                case ALL:
                  break;
              }

            break;

          case 3:

            // If mLsodaStatus == 3 we have found a root. This needs to be indicated to
            // the caller as it is not sufficient to rely on the fact that T < TOUT
            if (mLsodaStatus == 3)
              {
                // It is sufficient to switch to 2. Eventual state changes due to events
                // are indicated via the method stateChanged()
                mLsodaStatus = 2;
                Status = ROOT;
              }

            // The break statement is intentionally missing since we
            // have to continue to check the root masking state.
          default:

            switch (mRootMasking)
              {
                case NONE:
                case DISCRETE:
                  break;

                case ALL:
                {
                  const bool * pDiscrete = mDiscreteRoots.array();
                  bool * pMask = mRootMask.array();
                  bool * pMaskEnd = pMask + mNumRoots;
                  bool Destroy = true;

                  for (; pMask != pMaskEnd; ++pMask, ++pDiscrete)
                    {
                      if (*pMask)
                        {
                          if (*pDiscrete)
                            {
                              Destroy = false;
                            }
                          else
                            {
                              *pMask = false;
                            }
                        }
                    }

                  if (Destroy)
                    {
                      destroyRootMask();
                    }
                  else
                    {
                      mRootMasking = DISCRETE;
                    }

                  // We have to restart the integrator
                  mLsodaStatus = 1;
                }

                break;
              }

            break;
        }
    }
  else
    {
      mLSODA(&EvalF, //  1. evaluate F
             &mData.dim, //  2. number of variables
             mY, //  3. the array of current concentrations
             &mTime, //  4. the current time
             &EndTime, //  5. the final time
             &ITOL, //  6. error control
             &mRtol, //  7. relative tolerance array
             mAtol.array(), //  8. absolute tolerance array
             &mState, //  9. output by overshoot & interpolation
             &mLsodaStatus, // 10. the state control variable
             &one, // 11. further options (one)
             mDWork.array(), // 12. the double work array
             &DSize, // 13. the double work array size
             mIWork.array(), // 14. the int work array
             &ISize, // 15. the int work array size
             EvalJ, // 16. evaluate J (not given)
             &mJType);        // 17. the type of jacobian calculate (2)
    }

  // Why did we ignore this error?
  // if (mLsodaStatus == -1) mLsodaStatus = 2;

  mMethodState.setTime(mTime);
  *mpCurrentState = mMethodState;

  if ((mLsodaStatus <= 0))
    {
      Status = FAILURE;
      CCopasiMessage(CCopasiMessage::EXCEPTION, MCTrajectoryMethod + 6, mErrorMsg.str().c_str());
    }

  if (!mpCurrentState->isValid())
    {
      Status = FAILURE;
      CCopasiMessage(CCopasiMessage::EXCEPTION, MCTrajectoryMethod + 25, mTime);
    }

  return Status;
}