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