示例#1
0
// virtual
void CLsodaMethod::stateChanged()
{
  mMethodState = *mpCurrentState;
  mTime = mMethodState.getTime();
  mLsodaStatus = 1;

  destroyRootMask();
  mRootMasking = NONE;
}
示例#2
0
void CLsodaMethod::start(const CState * initialState)
{
  /* Retrieve the model to calculate */
  mpModel = mpProblem->getModel();

  /* Reset lsoda */
  mLsodaStatus = 1;
  mState = 1;
  mJType = 2;
  mErrorMsg.str("");

  /* Release previous state and make the initialState the current */
  mMethodState = *initialState;
  mTime = mMethodState.getTime();
  mTargetTime = mTime;
  mRootCounter = 0;

  mNumRoots = mpModel->getNumRoots();
  mRoots.resize(mNumRoots);
  destroyRootMask();
  mRootMasking = NONE;

  if (*mpReducedModel)
    mData.dim = mMethodState.getNumIndependent();
  else
    mData.dim = mMethodState.getNumIndependent() + mpModel->getNumDependentReactionMetabs();

  // When we have roots we need to add an artificial ODE dDummy/dt = 1
  if (mData.dim == 0 && mNumRoots != 0)
    {
      mData.dim = 1;
      mNoODE = true;
      mAtol.resize(1);
      mAtol[0] = *mpAbsoluteTolerance;
      mDummy = 0;
      mY = &mDummy;
    }
  else
    {
      mNoODE = false;
      mAtol = mpModel->initializeAtolVector(*mpAbsoluteTolerance, *mpReducedModel);
      mY = mMethodState.beginIndependent();
    }

  mYdot.resize(mData.dim);

  /* Configure lsoda(r) */
  mRtol = *mpRelativeTolerance;

  mDWork.resize(22 + mData.dim * std::max<C_INT>(16, mData.dim + 9) + 3 * mNumRoots);
  mDWork[4] = mDWork[5] = mDWork[6] = mDWork[7] = mDWork[8] = mDWork[9] = 0.0;
  mIWork.resize(20 + mData.dim);
  mIWork[4] = mIWork[6] = mIWork[9] = 0;

  mIWork[5] = *mpMaxInternalSteps;
  mIWork[7] = 12;
  mIWork[8] = 5;

  if (mNumRoots > 0)
    {
      mLSODAR.setOstream(mErrorMsg);
      mDiscreteRoots.resize(mNumRoots);

      CMathTrigger::CRootFinder * const* ppRootFinder = mpModel->getRootFinders().array();
      CMathTrigger::CRootFinder * const* ppRootFinderEnd = ppRootFinder + mNumRoots;
      bool * pDiscrete = mDiscreteRoots.array();

      for (; ppRootFinder != ppRootFinderEnd; ++ppRootFinder, ++pDiscrete)
        {
          *pDiscrete = (*ppRootFinder)->isDiscrete();
        }
    }
  else
    {
      mLSODA.setOstream(mErrorMsg);
    }

  return;
}
示例#3
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;
}
示例#4
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;
}
示例#5
0
// virtual
void CLsodaMethod::stateChanged()
{
  if (!mNoODE && mLsodaStatus != 1)
    {
      // Compare the independent state variables
      // This an be done directly by comparing mMethodState and *mpCurrentState
      C_FLOAT64 *pMethod = mY;
      C_FLOAT64 *pMethodEnd = pMethod + mData.dim;
      C_FLOAT64 *pCurrent = mpCurrentState->beginIndependent();

      for (; pMethod != pMethodEnd; ++pMethod, ++pCurrent)
        {
          // We may need to use the absolute and relative tolerance
          if (*pMethod != *pCurrent)
            {
              mLsodaStatus = 1;
              mMethodState = *mpCurrentState;
              mTime = mMethodState.getTime();

              break;
            }
        }

      if (mLsodaStatus != 1)
        {
          // Compare the rates of the independent state variables
          // we need to call evalF for mMethodState and *mpCurrentState and compare the returned rates.
          CVector< C_FLOAT64 > MethodRate(mData.dim);
          CVector< C_FLOAT64 > CurrentRate(mData.dim);

          evalF(&mTime, mY, MethodRate.array());

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

          evalF(&mTime, mY, CurrentRate.array());

          pMethod = MethodRate.array();
          pMethodEnd = pMethod + mData.dim;
          pCurrent = CurrentRate.array();

          for (; pMethod != pMethodEnd; ++pMethod, ++pCurrent)
            {
              // We may need to use the absolute and relative tolerance
              if (*pMethod != *pCurrent)
                {
                  mLsodaStatus = 1;
                  break;
                }
            }
        }
    }
  else
    {
      mMethodState = *mpCurrentState;
      mTime = mMethodState.getTime();
    }

  destroyRootMask();
  mRootMasking = NONE;
}