Пример #1
0
void orthogAug(
	double	*V,
	int		*rows,
	int		augment,
	int		*designFlag,
	int		N,
	int		k
	)
{
	int i;
	int j;
	double *pV;
	double *ppV;
	double scale;

	for (i=0;i<augment;i++) {
		ppV=pV=V+rows[i]*k;
		scale=0;
		j=k;
		while(j--) {
			scale+=(*ppV)*(*ppV);
			ppV++;
		}
		orthog(V,pV,designFlag,scale,N,k);		
	}

}
Пример #2
0
int nullify(
	double	*X,
	double	*V,
	int		augment,
	int		*rows,
	bool    *designFlag,
	int		N,
	int		k
	)
{
	int i;
	int newRow;
	int sizeT=N*k*sizeof(double);
	double scale;
	double tolerance=nullTol;

	memcpy((void*)V,(void*)X,sizeT);

	if (augment) {
		orthogAug(V,rows,augment,designFlag,N,k);
	}

	for (i=0;i<k-augment;i++) { 
		scale=getNextRow(V,N,k,designFlag,&newRow);
		if (scale<tolerance || newRow==-1)
			return(0); /* singular design. */
		if (i==0)
			tolerance=scale*nullTol;

		rows[i+augment]=newRow;
		designFlag[newRow]=true;

		if (i!=(k-1)) {
			orthog(V,V+newRow*k,designFlag,scale,N,k);
		}
	}

	return(1);
}
Пример #3
0
void CILDMMethod::step(const double & deltaT)
{
  C_INT failed_while = 0;

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

  C_INT i, j, k, info_schur = 0;
  mY_initial.resize(dim);
  mJacobian_initial.resize(dim, dim);
  mQ.resize(dim, dim);
  mR.resize(dim, dim);

  mQ_desc.resize(dim, dim);
  mR_desc.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 printing Jacobian

  // To get the reduced Stoichiometry Matrix;

  CMatrix<C_FLOAT64> Stoichiom;
  Stoichiom = mpModel -> getRedStoi();

  // const CCopasiVector< CReaction > & reacs = copasiModel->getReactions();
  C_INT32 reacs_size = mpModel -> getRedStoi().size();
  reacs_size = reacs_size / dim; //TODO what is this?

  /* 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[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);

#ifdef ILDMDEBUG

  if (flag_jacob == 0)
    {
      std::cout << "Jacobian_next:" << std::endl;
      std::cout << mJacobian << std::endl;
    }

#endif

// to be removed
  CMatrix<C_FLOAT64> Jacobian_for_test;
  Jacobian_for_test.resize(dim, dim);

  for (i = 0; i < dim; i++)
    for (j = 0; j < dim; j++)
      Jacobian_for_test(i, j) = mJacobian_initial(i, j);

  // 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);

  schur(info_schur);

#ifdef ILDMDEBUG
  std::cout << "Eigenvalues of next Jacobian" << std::endl;

  for (i = 0; i < dim; i++)
    std::cout << mR(i, i) << std::endl;

#endif

  for (i = 0; i < dim; i++)
    for (j = 0; j < dim; j++)
      mJacobian_initial(i, j) = Jacobian_for_test(i, j);

  //end to be removed

  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;

  schur(info_schur); // TO DO : move the test to the TSSAMethod

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

      goto integration;
    }

  C_INT flag_schur;
  flag_schur = 0;

#ifdef ILDMDEBUG

  std::cout << "Eigenvalues of initial Jacobian" << std::endl;

  for (i = 0; i < dim; i++)
    std::cout << mR(i, i) << std::endl;

  if (flag_schur == 1)
    {
      std::cout << "Schur Decomposition" << std::endl;
      std::cout << "mR - block upper triangular matrix :" << std::endl;
      std::cout << mR << std::endl;
    }

#endif

  /* If complex eigenvalues */

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

  // No reduction if the smallest eigenvalue is positive

  if (mR(dim - 1, dim - 1) >= 0)
    {
      slow = dim;
      fast = 0;

      CCopasiMessage(CCopasiMessage::WARNING,
                     MCTSSAMethod + 6, mTime - deltaT);

      failed = 1;
      goto integration;
    }

  // C_INT number, k;
  /** Classical ILDM iterations. The number of slow variables is decreased until the Deuflhard criterium holds */
  /*  do START slow iterations */

  while (slow > 1)
    {

      fast = fast + 1;
      slow = dim - fast;

      if (fast < dim - 1)
        if (mR(slow, slow) == mR(slow - 1 , slow - 1))
          fast = fast + 1;

      slow = dim - fast;

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

      C_INT info = 0;
      failed_while = 0;

      if (slow == 0)
        {
          for (i = 0; i < dim; i++)
            for (j = 0; j < dim; j++)
              {
                mTdInverse(i, j) = mQ(j, i);
                mTd(i, j) = mQ(i, j);
                mQz(i, j) = mR(i, j);
              }
        }
      else
        {
          /** Solution of Sylvester equation for given slow, mQ,mR
                Output: mTd, mTdinverse and mQz (mQz is used later for newton iterations) */
          sylvester(slow, info);

          if (info)
            {
              CCopasiMessage(CCopasiMessage::WARNING,
                             MCTSSAMethod + 7, slow, mTime - deltaT);

              failed_while = 1;
              goto integration;
            }
        }

      /* Check real parts of eigenvalues of Jacobian */

      for (i = slow ; i < dim; i++)
        if (mR(i , i) >= 0)
          {
            failed_while = 1;
            goto integration;
          }

      if (fast > 0)
        mEPS = 1 / fabs(mR(slow , slow));

      mCfast.resize(fast);

      /** Deuflhard Iteration:  Prove Deuflhard criteria, find consistent initial value for DAE
      output:  info - if Deuflhard is satisfied for this slow;
      transformation matrices mTd and mTdinverse */

      info = 0;

      C_INT help;
      help = 0;

      deuflhard(slow, info);
      help = help + 1;

      failed_while = 0;

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

  /** end of iterations to find the number of slow modes */

integration:

  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;

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

  mSlow = slow;

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

  //  test for orthogonality of the slow space

  C_INT flag_orthog = 1;

  if (flag_orthog == 0)
    {
      CMatrix<C_FLOAT64> orthog_prove;
      orthog_prove.resize(dim, dim);

      for (i = 0; i < dim; i++)
        for (j = 0; j < dim; j++)
          orthog_prove(i, j) = orthog(i, j);
    }

  C_INT flag_develop;
  flag_develop = 0; //1;

  if (flag_develop == 0)
    {
      C_INT info_schur_desc = 0;

      /** Schur  Decomposition of Jacobian (with another  sorting: from fast to slow).
        Output:  mQ_desc - transformation matrix
               mR_desc - block upper triangular matrix (with ordered eigenvalues) */

      schur_desc(info_schur_desc);

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

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

      C_INT slow_desc;
      slow_desc = fast;

      mat_anal_fast_space(slow_desc);
      mat_anal_mod_space(slow_desc);

      CVector<C_FLOAT64> Reac_slow_space_orth;
      Reac_slow_space_orth.resize(reacs_size);

      for (i = 0; i < reacs_size; i ++)
        {
          Reac_slow_space_orth[i] = 0;

          for (j = 0; j < dim; j++)
            {
              Reac_slow_space_orth[i] = Reac_slow_space_orth[i] + mVfast_space[j] * Stoichiom(j, i);
            }
        }

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

  // end of test

  // Post Analysis

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

  /** This part corresponds to the investigation of fast and slow reactions.  In  development at
   the moment. To activate the calculations take flag_develop = 0;
  */

  if (flag_develop == 0)
    {
      CMatrix<C_FLOAT64> Slow_react_contr;
      Slow_react_contr.resize(dim, reacs_size);

      CMatrix<C_FLOAT64> Mode_react_contr;
      Mode_react_contr.resize(dim, reacs_size);

      CVector<C_FLOAT64> Reac_slow_space;
      Reac_slow_space.resize(reacs_size);

      CVector<C_FLOAT64> Reac_fast_space;
      Reac_fast_space.resize(reacs_size);

      mReacSlowSpace.resize(reacs_size); //NEW TAB

      for (i = 0; i < dim; i ++)
        for (j = 0; j < reacs_size; j++)
          {
            Slow_react_contr(i, j) = 0;

            for (k = 0; k < dim; k++)
              Slow_react_contr(i, j) = Slow_react_contr(i, j) + mVslow(i, k) * Stoichiom(k, j);
          }

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

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

      for (i = 0; i < dim; i++)
        for (j = 0; j < reacs_size; j++)
          denom_mode[i] = denom_mode[i] + fabs(Slow_react_contr(i, j));

      for (i = 0; i < dim; i++)
        for (j = 0; j < reacs_size; j++)
          {
            if (denom_mode[i] == 0)
              Mode_react_contr(i, j) = 0;
            else
              Mode_react_contr(i, j) = (Slow_react_contr(i, j)) / denom_mode[i] * 100;
          }

      CVector<C_FLOAT64> denom_reac;
      denom_reac.resize(reacs_size);

      for (j = 0; j < reacs_size; j++)
        denom_reac[j] = 0;

      for (i = 0; i < reacs_size; i++)
        for (j = 0; j < dim; j++)
          denom_reac[i] = denom_reac[i] + fabs(Slow_react_contr(j, i));

      for (i = 0; i < reacs_size; i++)
        for (j = 0; j < dim; j++)
          {
            if (denom_reac[i] == 0)
              Slow_react_contr(j, i) = 0;
            else
              Slow_react_contr(j, i) = (Slow_react_contr(j , i)) / denom_reac[i] * 100;
          }

      for (i = 0; i < reacs_size; i ++)
        {
          Reac_slow_space[i] = 0;

          for (j = 0; j < dim; j++)
            {
              Reac_slow_space[i] = Reac_slow_space[i] + mVslow_space[j] * Stoichiom(j, i);
            }
        }

      C_FLOAT64 length;
      length = 0;

      for (i = 0; i < reacs_size; i++)
        length = length + fabs(Reac_slow_space[i]);

      for (i = 0; i < reacs_size; i++)
        if (length > 0)
          mReacSlowSpace[i] = Reac_slow_space[i] / length * 100;
        else
          mReacSlowSpace[i] = 0;

      for (i = 0; i < reacs_size; i ++)
        {
          Reac_fast_space[i] = 0;

          for (j = 0; j < dim; j++)
            Reac_fast_space[i] = Reac_fast_space[i] + mVfast_space[j] * Stoichiom(j, i);
        }

      length = 0;

      for (i = 0; i < reacs_size; i++)
        length = length + fabs(Reac_fast_space[i]);

      for (i = 0; i < reacs_size; i++)
        if (length > 0)
          Reac_fast_space[i] = Reac_fast_space[i] / length * 100;
        else
          Reac_fast_space[i] = 0;

#ifdef ILDMDEBUG

      std::cout << "**********************************************************" << std::endl;
      std::cout << "**********************************************************" << std::endl;
      std::cout << std::endl;
      std::cout << std::endl;
#endif

      mTMP1.resize(reacs_size, dim);
      mTMP2.resize(reacs_size, dim);
      mTMP3.resize(reacs_size, 1);

      for (i = 0; i < dim; i++)
        for (j = 0; j < reacs_size; j++)
          {
            mTMP1(j, i) = Mode_react_contr(i, j);
            mTMP2(j, i) = Slow_react_contr(i, j);
          }

      for (j = 0; j < reacs_size; j++)
        mTMP3(j, 0) = Reac_fast_space[j];
    }

  // End of reaction analysis

  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;
}