void CILDMModifiedMethod::newton_for_timestep(C_INT metabolite_number, C_FLOAT64 & y_consistent, C_INT & info)
{
  C_INT i, iter, itermax, flag_newton;
  iter = 0;
  itermax = 150;

  flag_newton = 1;  // set flag_newton=0 to print the iteration steps

  C_FLOAT64 tol, err;
  tol = 1e-6;
  err = 10.0;

  C_INT dim = mData.dim;

  C_FLOAT64 d_y, deriv;
  d_y = 0;
  deriv = mJacobian_initial(metabolite_number, metabolite_number);

  if (deriv == 0)
    {
      return;
    }

  info = 0;

  C_FLOAT64 number2conc = mpModel->getNumber2QuantityFactor() / mpModel->getCompartments()[0]->getInitialValue();
  //C_FLOAT62number2conc = 1.;

  //this is an ugly hack that only makes sense if all metabs are in the same compartment
  //at the moment is is the only case the algorithm deals with

  CVector<C_FLOAT64> y_newton; //current state converted to concentrations
  y_newton.resize(dim);

  for (i = 0; i < dim; ++i)
    y_newton[i] = mY_initial[i] * number2conc;

  CVector<C_FLOAT64> dydt;
  dydt.resize(dim);

  while (err > tol)
    {
      iter ++;

      if (iter > itermax)
        {
          info = 1;
          break;
        }

      y_newton[metabolite_number] = y_newton[metabolite_number] + d_y;

      calculateDerivativesX(y_newton.array(), dydt.array());

      d_y = - 1 / deriv * dydt[metabolite_number];

      if (err > fabs(d_y))
        err = fabs(d_y);
    }

  y_consistent = y_newton[metabolite_number];

  return;
}
void CILDMModifiedMethod::newton_new(C_INT *index_metab, C_INT & slow, C_INT & info)
{
  C_INT i, j, k, m, iter, iterations, itermax;
  C_INT nrhs, ok, fast, flag_newton;

  flag_newton = 1;  // set flag_newton=1  to print temporaly steps of newton iterations

  C_FLOAT64 tol, err;
  C_INT dim = mData.dim;

  fast = dim - slow;

  CVector<C_INT> ipiv;
  ipiv.resize(fast);

  CVector<C_FLOAT64> s_22_array;
  s_22_array.resize(fast*fast);

  CVector<C_FLOAT64> gf_newton;
  gf_newton.resize(fast);

  CVector<C_FLOAT64> d_yf;
  d_yf.resize(dim);

  CVector<C_FLOAT64> y_newton;
  y_newton.resize(dim);

  CVector<C_FLOAT64> yf_newton;
  yf_newton.resize(fast);

  CVector<C_FLOAT64> dydt_newton;
  dydt_newton.resize(dim);

  CVector<C_FLOAT64> g_newton;
  g_newton.resize(dim);

  CMatrix<C_FLOAT64> Jac_fast;
  Jac_fast.resize(fast, fast);

  C_FLOAT64 g1, g2 = 0.0;
  mY_cons.resize(dim);

  nrhs = 1;
  tol = 1e-6;
  err = 10.0;
  iter = 0;

  itermax = 150;
  iterations = 0;

  info = 0;

  C_FLOAT64 number2conc = mpModel->getNumber2QuantityFactor() / mpModel->getCompartments()[0]->getInitialValue();
  //C_FLOAT64 number2conc = 1.;

  for (i = 0; i < fast; i++)
    {
      m = index_metab[i];

      for (j = 0; j < fast; j++)
        {
          k = index_metab[ j];

          if ((m > -1) & (k > -1))
            Jac_fast(i, j) = mJacobian_initial(m, k);
          else
            {
              info = 3;
              return;
            }
        }
    }

  for (i = 0; i < dim; i++)
    y_newton[i] = mY_initial[i] * number2conc;

  for (i = 0; i < fast; i++)
    for (j = 0; j < fast; j++)
      s_22_array[j + fast*i] = Jac_fast(j, i);

  for (i = 0; i < dim; i++)
    d_yf[i] = 0.;

  while (err > tol)
    {
      iter ++;

      if (iter > itermax)
        {
          info = 1;
          return;
        }

      for (i = 0; i < dim; i++)
        y_newton[i] = y_newton[i] + d_yf[i];

      calculateDerivativesX(y_newton.array(), dydt_newton.array());

      for (i = 0; i < fast; i++)
        {
          j = index_metab[i];
          gf_newton[i] = -1. * dydt_newton[j];
        }

      /*       int dgesv_(integer *n, integer *nrhs, doublereal *a, integer
       * *lda, integer *ipiv, doublereal *b, integer *ldb, integer *info)
       *
       *  -- LAPACK driver routine (version 3.0) --
       *     Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
       *     Courant Institute, Argonne National Lab, and Rice University
       *     March 31, 1993
       *
       *
       *  Purpose
       *  =======
       *
       *  DGESV computes the solution to a real system of linear equations
       *     A * X = B,
       *  where A is an N-by-N matrix and X and B are N-by-NRHS matrices.
       *
       *  The LU decomposition with partial pivoting and row interchanges is
       *  used to factor A as
       *     A = P * L * U,
       *  where P is a permutation matrix, L is unit lower triangular, and U is
       *  upper triangular.  The factored form of A is then used to solve the
       *  system of equations A * X = B.
       *
       *  Arguments
       *  =========
       *
       *  N       (input) INTEGER
       *          The number of linear equations, i.e., the order of the
       *          matrix A.  N >= 0.
       *
       *  NRHS    (input) INTEGER
       *          The number of right hand sides, i.e., the number of columns
       *          of the matrix B.  NRHS >= 0.
       *
       *  A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
       *          On entry, the N-by-N coefficient matrix A.
       *          On exit, the factors L and U from the factorization
       *          A = P*L*U; the unit diagonal elements of L are not stored.
       *
       *  LDA     (input) INTEGER
       *          The leading dimension of the array A.  LDA >= max(1,N).
       *
       *  IPIV    (output) INTEGER array, dimension (N)
       *          The pivot indices that define the permutation matrix P;
       *          row i of the matrix was interchanged with row IPIV(i).
       *
       *  B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
       *          On entry, the N-by-NRHS matrix of right hand side matrix B.
       *          On exit, if INFO = 0, the N-by-NRHS solution matrix X.
       *
       *  LDB     (input) INTEGER
       *          The leading dimension of the array B.  LDB >= max(1,N).
       *
       *
       * INFO    (output) INTEGER
       *          = 0:  successful exit
       *          < 0:  if INFO = -i, the i-th argument had an illegal value
       *          > 0:  if INFO = i, U(i,i) is exactly zero.  The factorization
       *                has been completed, but the factor U is exactly
       *                singular, so the solution could not be computed.
       */

      dgesv_(&fast, &nrhs, s_22_array.array(), &fast, ipiv.array(), gf_newton.array(), &fast, &ok);

      if (ok != 0)
        {
          info = 2;
          return;
        }

      for (i = 0; i < fast; i++)
        d_yf[i] = 0;

      for (j = 0; j < fast; j++)
        {
          k = index_metab[j];

          for (i = 0; i < dim; i ++)
            {
              if (i == k)
                d_yf[k] = gf_newton[j];
            }
        }

      err = -10.;

      for (i = 0; i < fast; i++)
        {
          gf_newton[i] = fabs(gf_newton[i]);

          if (err < gf_newton[i])
            err = gf_newton[i];
        }

      iterations = iterations + 1;

      // stop criterion of newton method

      //   C_FLOAT64 g1, g2 = 0.0;

      //   g2 = err;

      if (iter == 1)
        g1 = 3.0 * err;
      else
        g1 = g2;

      g2 = err;

      if (g2 / g1 > 1.0)
        {
          info = 1;
          return;
        }
    } /* end while */

  for (i = 0; i < dim; i++)
    mY_cons[i] = y_newton[i];

  info = 0;

  return;
}
/**
  Deuflhard Iteration:  Prove Deuflhard criteria, find consistent initial value for DAE
  output:  info - if Deuflhard is satisfied
 */
void CILDMModifiedMethod::deuflhard_metab(C_INT & slow, C_INT & info)
{
  C_INT i, j, info_newton;
  C_INT dim = mData.dim;
  C_INT fast = dim - slow;

  C_INT flag_deufl;

  flag_deufl = 1;  // set flag_deufl=0  to print temporaly steps for this function

  C_FLOAT64 max = 0;
  CVector<C_FLOAT64> re;
  CVector<C_FLOAT64> dxdt_relax;
  CVector<C_FLOAT64> x_relax;
  CVector<C_FLOAT64> x_help;
  CVector<C_FLOAT64> dxdt;

  CVector<C_FLOAT64> help;
  help.resize(dim);
  CVector<C_INT> index;
  index.resize(dim);
  CVector<C_INT> index_temp;
  index_temp.resize(dim);

  C_FLOAT64 eps;
  eps = 1 / fabs(mR(dim - fast , dim - fast));
  //eps = fabs(mR(dim - fast - 1, dim - fast - 1)) / fabs(mR(dim - fast , dim - fast));

  mat_anal_fast_space(slow);

  for (i = 0; i < dim; i++)
    {
      index[i] = i;
      index_temp[i] = i;
    }

  for (i = 0; i < dim; i++)
    {
      help[i] = mVfast_space[i];
    }

  evalsort(help.array(), index.array(), dim);

  for (i = 0; i < dim; i++)
    index_temp[i] = index[i];

  for (i = 0; i < dim; i++)
    {
      index[i] = index_temp[dim - i - 1];
    }

  C_FLOAT64 number2conc = mpModel->getNumber2QuantityFactor() / mpModel->getCompartments()[0]->getInitialValue();
  //C_FLOAT64 number2conc = 1.;

  dxdt.resize(dim);

  for (j = 0; j < dim; j++)
    dxdt[j] = 0.;

  //CVector<C_FLOAT64> x_help;
  x_help.resize(dim);

  for (j = 0; j < dim; j++)
    {
      x_help[j] = mY_initial[j] * number2conc;
    }

  // mpModel->calculateDerivativesX(dxdt.array());
  calculateDerivativesX(x_help.array(), dxdt.array());

  info_newton = 0;

  newton_new(index.array(), slow, info_newton);

  if (info_newton)
    {
      // TODO
      info = 1;
      return;
    }

  x_relax.resize(dim);

  for (i = 0; i < dim; i++)
    x_relax[i] = mY_cons[i];

  //CVector<C_FLOAT64> dxdt_relax;
  dxdt_relax.resize(dim);

  calculateDerivativesX(x_relax.array(), dxdt_relax.array());

  //CVector<C_FLOAT64> re;
  re.resize(dim);

  // stop criterion for slow reaction modes

  for (i = 0; i < dim; i++)
    {
      re[i] = fabs(dxdt_relax[i] - dxdt[i]);
      re[i] = re[i] * eps;

      for (j = 0; j < fast; j ++)
        if (i == index[j])
          re[i] = 0;
    }

  for (i = 0; i < dim; i++)
    if (max < re[i])
      max = re[i];

  if (max >= mDtol)
    info = 1;
  else
    info = 0;

  return;
}
void CILDMModifiedMethod::step(const double & deltaT)
{

  C_INT dim = mData.dim;
  C_INT fast = 0;
  C_INT slow = dim - fast;

  C_INT slow2, fast2;

  slow2 = dim;
  fast2 = dim - slow2;

  C_INT i, j;

  mY_initial.resize(dim);
  mJacobian_initial.resize(dim, dim);
  mQ.resize(dim, dim);
  mR.resize(dim, dim);
  mTd.resize(dim, dim);
  mTdInverse.resize(dim, dim);
  mQz.resize(dim, dim);

  mTd_save.resize(dim, dim);

  mTdInverse_save.resize(dim, dim);

  mpModel->updateSimulatedValues(mReducedModel);
  // TO REMOVE : mpModel->applyAssignments();
  mpModel->calculateJacobianX(mJacobian, 1e-6, 1e-12);

  C_INT flag_jacob;
  flag_jacob = 1;  // Set flag_jacob=0 to print Jacobian

  C_FLOAT64 number2conc = mpModel->getNumber2QuantityFactor() / mpModel->getCompartments()[0]->getInitialValue();
  //C_FLOAT64 number2conc = 1.;

  //this is an ugly hack that only makes sense if all metabs are in the same compartment
  //at the moment is is the only case the algorithm deals with

  CVector<C_FLOAT64> Xconc; //current state converted to concentrations
  Xconc.resize(dim);

  for (i = 0; i < dim; ++i)
    Xconc[i] = mY[i] * number2conc;

  for (i = 0; i < dim; i++)
    mY_initial[i] = mY[i];

  CVector<C_FLOAT64> Xconc_initial; //current state converted to concentrations
  Xconc_initial.resize(dim);

  for (i = 0; i < dim; ++i)
    Xconc_initial[i] = mY_initial[i] * number2conc;

  // save initial  Jacobian before next time step
  for (i = 0; i < dim; i++)
    for (j = 0; j < dim; j++)
      mJacobian_initial(i, j) = mJacobian(i, j);

  // Next time step
  integrationStep(deltaT);

  mpModel->updateSimulatedValues(mReducedModel);
  // TO REMOVE : mpModel->applyAssignments();

  // Calculate Jacobian for time step control
  mpModel->calculateJacobianX(mJacobian, 1e-6, 1e-12);

  //CMatrix<C_FLOAT64> mTd_save;
  for (i = 0; i < dim; i++)
    for (j = 0; j < dim; j++)
      {
        mTd_save(i, j) = 0;
        mTdInverse_save(i, j) = 0;
      }

  for (i = 0; i < dim; i++)
    for (j = 0; j < dim; j++)
      {
        mTd(i, j) = 0;
        mTdInverse(i, j) = 0;
      }

  /** Schur  Decomposition of Jacobian (reordered).
  Output:  mQ - transformation matrix mR - block upper triangular matrix (with ordered eigenvalues) */

  C_INT failed = 0;
  C_INT info_schur = 0;

  C_INT number, k;
  C_INT failed_while = 0;

  C_INT flag_deufl;
  flag_deufl = 1;

  C_FLOAT64 max = 0.;

  //C_FLOAT64 max = 0;
  CVector<C_FLOAT64> re;
  CVector<C_FLOAT64> dxdt_relax;
  CVector<C_FLOAT64> x_relax;
  CVector<C_FLOAT64> x_help;
  CVector<C_FLOAT64> dxdt;

  CVector<C_FLOAT64> x_zero;

  CVector<C_FLOAT64> dxdt_zero;

  CVector<C_FLOAT64> dxdt_real;

  CVector<C_FLOAT64> help;

  CVector<C_INT> index;
  CVector<C_INT> index_temp;
  CMatrix<C_FLOAT64> orthog_prove;
  orthog_prove.resize(dim, dim);

  C_INT info;

  CVector<C_INT> index_metab;
  index_metab.resize(dim);

  /** Schur transformation of Jacobian */
  schur(info_schur);

  if (info_schur)
    {
      CCopasiMessage(CCopasiMessage::WARNING,
                     MCTSSAMethod + 9, mTime - deltaT);

      goto integration;
    }

  for (i = 0; i < dim; i++)
    for (j = 0; j < dim; j++)
      mTdInverse(i, j) = mQ(j, i);

  C_INT flag_schur;

  flag_schur = 1;  // set flag_schur = 0 to print Schur decomposition of jacobian (matrices mR and transformation mQ)

  mY_cons.resize(dim);  // consistent initial vector for DAE

  /* If complex eigenvalues */
  //BUG 873
  if (mR(dim - 1, dim - 1) == mR(dim - 2 , dim - 2))
    if (dim == 2)
      {
        slow = dim;
        goto integration;
      }

  // If positive eigenvalues

  if (mR(dim - 1, dim - 1) >= 0)
    {
      slow = dim;
      fast = 0;
      CCopasiMessage(CCopasiMessage::WARNING,
                     MCTSSAMethod + 10, mTime - deltaT);

      failed = 1;
      goto integration;
    }

  // Iterations to determine the number of slow metabolites

  while ((slow2 > 1))
    {
      slow2 = slow2 - 1;
      fast2 = dim - slow2;

      if (mR(dim - fast2, dim - fast2) >= 0)
        {
          failed = 1;
          goto integration;
        }

      deuflhard_metab(slow2, info);

      if (info)
        {
          failed_while = 1;
          goto integration;
        }
    }

  //end of iterations to determine the number of slow metabolites

  /** end of the block %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  */
  /** %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  */

integration:

  slow = slow2;
  fast = fast2;

  if ((failed == 1) || (failed_while == 1))
    {
      if (slow < dim)
        {
          fast = fast - 1;
          slow = dim - fast;

          if ((fast >= 1) && (mR(slow - 1, slow - 1) == mR(slow , slow)))
            fast = fast - 1;

          slow = dim - fast;
        }
    }

  mSlow = slow;

  if (slow == dim)
    CCopasiMessage(CCopasiMessage::WARNING,
                   MCTSSAMethod + 11, mTime);

  for (i = 0; i < dim; i++)
    for (j = 0; j < dim; j++)
      // mTdInverse(i,j) = mQ(i,j);
      mTd(i, j) = mQ(i, j);

  // Flag for print Tabs

  mat_anal_mod(slow);
  mat_anal_metab(slow);
  mat_anal_mod_space(slow);
  mat_anal_fast_space(slow);

  // This block proves which metabolite could be considered as QSS. In development
  /** Begin of the block %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  */

  C_INT flag_dev;
  flag_dev = 1;

  if (flag_dev == 0)
    {
      C_INT temp;
      temp = dim - 1;

      // Mode Analysis to find the dominant metabolites in the modes
      mat_anal_mod(temp);

      //index_metab = -1, if there is no dominant metabolites in corresponding mode,
      //and is equal
      // to the number of dominant metabolite in opposite case
      // Dominant metabolite - its contribution to the mode is larger as 70%

      for (j = 0; j < dim; j++)
        index_metab[j] = -1;

      for (i = 0; i < dim ; i ++)
        for (j = 0; j < dim; j++)
          if (mVslow(dim - i - 1, j) > 70)
            index_metab[i] = j;

      C_FLOAT64 y_cons;

      info = 0;
      k = 0;
      number = index_metab[k];

      if (number > - 1)
        newton_for_timestep(number, y_cons, info);

      while (k < dim - 1)
        {
          if (number > -1)
            {
              dxdt.resize(dim);

              for (j = 0; j < dim; j++)
                dxdt[j] = 0.;

              //CVector<C_FLOAT64> x_help;
              x_help.resize(dim);

              for (j = 0; j < dim; j++)
                {
                  x_help[j] = mY_initial[j] * number2conc;
                }

              calculateDerivativesX(x_help.array(), dxdt.array());
              info = 0;

              //NEWTON: Looking for consistent initial value for DAE system
              //Output:  y_cons, info

              newton_for_timestep(number, y_cons, info);

              if (info)
                {
                  // TODO info: newton iteration stop
                }

              if (info == 0)
                {
                  // CVector<C_FLOAT64> x_relax;
                  x_relax.resize(dim);

                  for (i = 0; i < dim; i ++)
                    if (i == number)
                      x_relax[i] = y_cons;
                    else
                      x_relax[i] = x_help[i];

                  //CVector<C_FLOAT64> dxdt_relax;
                  dxdt_relax.resize(dim);

                  calculateDerivativesX(x_relax.array(), dxdt_relax.array());

                  //CVector<C_FLOAT64> re;
                  re.resize(dim);

                  C_FLOAT64 eps;
                  eps = 1 / fabs(mR(dim - k - 1 , dim - k - 1));

                  // stop criterion for slow reaction modes

                  for (i = 0; i < dim; i++)
                    {
                      if (i == number)
                        re[i] = 0;
                      else
                        {
                          re[i] = fabs(dxdt_relax[i] - dxdt[i]);
                          re[i] = re[i] * eps;
                        }
                    }

                  //C_FLOAT64 max = 0.;
                  for (i = 0; i < dim; i++)
                    if (max < re[i])
                      max = re[i];

                  if (max >= mDtol)
                    info = 1;
                  else
                    info = 0;
                }
            }

          k = k + 1;
          number = index_metab[k];
          max = 0;
        }
    }

  /** end of the of block %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  */
  /** %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  */

  mpModel->updateSimulatedValues(mReducedModel);
  // TO REMOVE : mpModel->applyAssignments();

  // Calculate Jacobian for time step control

  mpModel->calculateJacobianX(mJacobian, 1e-6, 1e-12);

  // new entry for every entry contains the current data of currently step
  setVectors(slow);

  // set the stepcounter
  mCurrentStep += 1;

  return;
}
Example #5
0
/**
  Deuflhard Iteration:  Prove Deuflhard criteria, find consistent initial value for DAE
  output:  info - if Deuflhard is satisfied for given slow; transformation matrices
  mTd and mTdinverse
 */
void CILDMMethod::deuflhard(C_INT & slow, C_INT & info)
{
  C_INT i, j;
  C_INT dim = mData.dim;
  C_INT fast = dim - slow;
  C_INT flag_deufl;


  flag_deufl = 1;  // set flag_deufl = 0 to print the results of calculations

  /* calculations before relaxing yf to slow manifold */

  CVector<C_FLOAT64> c_full;
  c_full.resize(dim);

  CVector<C_FLOAT64> c_slow;
  c_slow.resize(slow);

  /* the vector mY is the current state of the system*/

  C_FLOAT64 number2conc =  1.; // mpModel->getNumber2QuantityFactor()
  // / mpModel->getCompartments()[0]->getInitialValue();

  //this is an ugly hack that only makes sense if all metabs are in the same compartment
  //at the moment is is the only case the algorithm deals with

  CVector<C_FLOAT64> Xconc; //current state converted to concentrations
  Xconc.resize(dim);

  for (i = 0; i < dim; ++i)
    Xconc[i] = mY_initial[i] * number2conc;

  for (i = 0; i < dim; i++)
    {
      c_full[i] = 0.0;

      for (j = 0; j < dim; j++)
        c_full[i] = c_full[i] + mTdInverse(i, j) * Xconc[j];
    }

  for (j = 0; j < slow; j++)
    c_slow[j] = c_full[j];

  for (j = 0; j < fast; j++)
    mCfast[j] = c_full[j + slow];

  CVector<C_FLOAT64> g_full;
  g_full.resize(dim);

  CVector<C_FLOAT64> g_slow;
  g_slow.resize(slow);

  CVector<C_FLOAT64> g_fast;
  g_fast.resize(fast);

  CVector<C_FLOAT64> dxdt;
  dxdt.resize(dim);

  mpModel->updateSimulatedValues(mReducedModel);

  for (j = 0; j < dim; j++)
    dxdt[j] = 0.;

  CVector<C_FLOAT64> x_help;
  x_help.resize(dim);

  for (j = 0; j < dim; j++)
    {
      x_help[j] = mY_initial[j] * number2conc;
    }

  calculateDerivativesX(x_help.array(), dxdt.array());

  for (i = 0; i < dim; i++)
    {
      g_full[i] = 0.0;

      for (j = 0; j < dim; j++)
        g_full[i] = g_full[i] + mTdInverse(i, j) * dxdt[j];
    }

  for (j = 0; j < slow; j++)
    g_slow[j] = g_full[j];

  info = 0;

  /**  NEWTON: Looking for consistent initial value for DAE system
  Output:  mCfast, info */
  newton(c_slow.array(), slow, info);


  if (info)
    {
      /* TODO */

      return;
    }


  /* calculation of g_relax at point x_relax (after relaxing yf to slow manifold)*/

  CVector<C_FLOAT64> c_relax;
  c_relax.resize(dim);

  CVector<C_FLOAT64> x_relax;
  x_relax.resize(dim);

  CVector<C_FLOAT64> dxdt_relax;
  dxdt_relax.resize(dim);

  CVector<C_FLOAT64> g_relax;
  g_relax.resize(dim);

  for (i = 0; i < slow; i++)
    c_relax[i] = c_slow[i];

  for (i = slow; i < dim; i++)
    c_relax[i] = mCfast[i - slow];

  for (i = 0; i < dim; i++)
    {
      x_relax[i] = 0.0;

      for (j = 0; j < dim; j++)
        x_relax[i] = x_relax[i] + mTd(i, j) * c_relax[j];
    }

  calculateDerivativesX(x_relax.array(), dxdt_relax.array());

  for (i = 0; i < dim; i++)
    {
      g_relax[i] = 0.0;

      for (j = 0; j < dim; j++)
        g_relax[i] = g_relax[i] + mTdInverse(i, j) * dxdt_relax[j];
    }

  CVector<C_FLOAT64> re;
  re.resize(slow);

  /* stop criterion for slow reaction modes */

  for (i = 0; i < slow; i++)
    {
      re[i] = fabs(g_relax[i] - g_slow[i]);
      re[i] = re[i] * mEPS;



    }

  C_FLOAT64 max = 0.;

  for (i = 0; i < slow; i++)
    if (max < re[i])
      max = re[i];

  C_FLOAT64 max1;
  C_FLOAT64 norm = 0;

  for (i = 0; i < slow; i++)
    norm = norm + fabs(g_relax[i] - g_slow[i]);

  max1 = norm * mEPS;

  if (max >= mDtol / mpModel->getNumber2QuantityFactor())
    info = 1;
  else
    info = 0;

  return;
}
Example #6
0
void CILDMMethod::newton(C_FLOAT64 *ys, C_INT & slow, C_INT & info)
{
  C_INT i, j, iter, iterations, itermax;
  C_INT nrhs, ok, fast;

  C_FLOAT64 tol, err;
  C_INT dim = mData.dim;

  fast = dim - slow;

  CVector<C_INT> ipiv;
  ipiv.resize(fast);

  CVector<C_FLOAT64> s_22_array;
  s_22_array.resize(fast*fast);

  CVector<C_FLOAT64> gf_newton;
  gf_newton.resize(fast);

  CVector<C_FLOAT64> d_yf;
  d_yf.resize(fast);

  CVector<C_FLOAT64> y_newton;
  y_newton.resize(dim);

  CVector<C_FLOAT64> yf_newton;
  yf_newton.resize(fast);

  CVector<C_FLOAT64> x_newton;
  x_newton.resize(dim);

  CVector<C_FLOAT64> dxdt_newton;
  dxdt_newton.resize(dim);

  CVector<C_FLOAT64> g_newton;
  g_newton.resize(dim);

  CMatrix<C_FLOAT64> S_22;
  S_22.resize(fast, fast);

  C_FLOAT64 g1, g2 = 0;

  nrhs = 1;
  //tol = 1e-9;
  tol = 1e-9 / mpModel->getNumber2QuantityFactor();


  err = 10.0 / mpModel->getNumber2QuantityFactor();
  iter = 0;

  itermax = 100;
  iterations = 0;

  info = 0;

  for (i = 0; i < fast; i++)
    for (j = 0; j < fast; j++)
      S_22(i, j) = mQz(i, j);

  for (i = 0; i < fast; i++)
    yf_newton[i] = mCfast[i];

  for (i = 0; i < fast; i++)
    for (j = 0; j < fast; j++)
      s_22_array[j + fast*i] = S_22(j, i);

  for (i = 0; i < fast; i++)
    d_yf[i] = 0.;

  while (err > tol)
    {
      iter ++;

      if (iter > itermax)
        {

          info = 1;
          return;
        }

      for (i = 0; i < fast; i++)
        yf_newton[i] = yf_newton[i] + d_yf[i];

      /* back transformation */

      for (i = 0; i < slow; i++)
        y_newton[i] = ys[i];

      for (i = slow; i < dim; i++)
        y_newton[i] = yf_newton[i - slow];

      for (i = 0; i < dim; i++)
        {
          x_newton[i] = 0.0;

          for (j = 0; j < dim; j++)
            x_newton[i] = x_newton[i] + mTd(i, j) * y_newton[j];
        }

      calculateDerivativesX(x_newton.array(), dxdt_newton.array());

      for (i = 0; i < dim; i++)
        {
          g_newton[i] = 0.;

          for (j = 0; j < dim; j++)
            g_newton[i] = g_newton[i] + mTdInverse(i, j) * dxdt_newton[j];
        }

      // for (i = 0; i < fast; i++)
      //  gf_newton[i] = -1. * g_newton[i + slow];

      for (i = 0; i < fast; i++)
        {
          gf_newton[i] = -1. * g_newton[i + slow];

        }

      /*       int dgesv_(integer *n, integer *nrhs, doublereal *a, integer
       * *lda, integer *ipiv, doublereal *b, integer *ldb, integer *info)
       *
       *  -- LAPACK driver routine (version 3.0) --
       *     Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
       *     Courant Institute, Argonne National Lab, and Rice University
       *     March 31, 1993
       *
       *
       *  Purpose
       *  =======
       *
       *  DGESV computes the solution to a real system of linear equations
       *     A * X = B,
       *  where A is an N-by-N matrix and X and B are N-by-NRHS matrices.
       *
       *  The LU decomposition with partial pivoting and row interchanges is
       *  used to factor A as
       *     A = P * L * U,
       *  where P is a permutation matrix, L is unit lower triangular, and U is
       *  upper triangular.  The factored form of A is then used to solve the
       *  system of equations A * X = B.
       *
       *  Arguments
       *  =========
       *
       *  N       (input) INTEGER
       *          The number of linear equations, i.e., the order of the
       *          matrix A.  N >= 0.
       *
       *  NRHS    (input) INTEGER
       *          The number of right hand sides, i.e., the number of columns
       *          of the matrix B.  NRHS >= 0.
       *
       *  A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
       *          On entry, the N-by-N coefficient matrix A.
       *          On exit, the factors L and U from the factorization
       *          A = P*L*U; the unit diagonal elements of L are not stored.
       *
       *  LDA     (input) INTEGER
       *          The leading dimension of the array A.  LDA >= max(1,N).
       *
       *  IPIV    (output) INTEGER array, dimension (N)
       *          The pivot indices that define the permutation matrix P;
       *          row i of the matrix was interchanged with row IPIV(i).
       *
       *  B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
       *          On entry, the N-by-NRHS matrix of right hand side matrix B.
       *          On exit, if INFO = 0, the N-by-NRHS solution matrix X.
       *
       *  LDB     (input) INTEGER
       *          The leading dimension of the array B.  LDB >= max(1,N).
       *
       *
       * INFO    (output) INTEGER
       *          = 0:  successful exit
       *          < 0:  if INFO = -i, the i-th argument had an illegal value
       *          > 0:  if INFO = i, U(i,i) is exactly zero.  The factorization
       *                has been completed, but the factor U is exactly
       *                singular, so the solution could not be computed.
       */

      dgesv_(&fast, &nrhs, s_22_array.array(), &fast, ipiv.array(), gf_newton.array(), &fast, &ok);

      if (ok != 0)
        {

          info = 2;
          break;
        }

      for (i = 0; i < fast; i++)
        d_yf[i] = gf_newton[i];

      err = -10.;

      /*      for (i = 0; i < fast; i++)
              {
                gf_newton[i] = fabs(gf_newton[i]);

                if (err < gf_newton[i])
                  err = gf_newton[i];
              }

      */


      for (i = 0; i < fast; i++)
        {
          gf_newton[i] = fabs(gf_newton[i]);

          if (err < gf_newton[i])
            err = gf_newton[i];
        }




      iterations = iterations + 1;

      /* stop criterion of newton method */

      //  C_FLOAT64 g1, g2;

      //  g2 = err;

      if (iter == 1)
        g1 = 3.0 * err;
      else
        g1 = g2;

      g2 = err;


      if (g2 / g1 > 1.0)
        {

          info = 1;
          break;
        }
    } /* end while */

  for (i = 0; i < fast; i++)
    mCfast[i] = yf_newton[i];

  return;
}