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