inline bool solveInvertible(const DMat<RT>& A, const DMat<RT>& B, DMat<RT>& X) { DMatLinAlg<RT> LUdecomp(A); return LUdecomp.solveInvertible(B,X); }
inline M2_arrayintOrNull LU(const DMat<RT>& A, DMat<RT>& L, DMat<RT>& U) { std::vector<size_t> perm; DMatLinAlg<RT> LUdecomp(A); LUdecomp.matrixPLU(perm, L, U); return stdvector_to_M2_arrayint(perm); }
inline M2_arrayintOrNull rankProfile(const DMat<RT>& A, bool row_profile) { std::vector<size_t> profile; if (row_profile) { // First transpose A DMat<RT> B(A.ring(), A.numColumns(), A.numRows()); MatrixOps::transpose(A,B); DMatLinAlg<RT> LUdecomp(B); LUdecomp.columnRankProfile(profile); return stdvector_to_M2_arrayint(profile); } else { DMatLinAlg<RT> LUdecomp(A); LUdecomp.columnRankProfile(profile); return stdvector_to_M2_arrayint(profile); } }
inline size_t nullSpace(const DMat<RT>& A, DMat<RT>& result_nullspace) { DMatLinAlg<RT> LUdecomp(A); return LUdecomp.kernel(result_nullspace); }
inline bool inverse(const DMat<RT>& A, DMat<RT>& result_inv) { DMatLinAlg<RT> LUdecomp(A); return LUdecomp.inverse(result_inv); }
inline size_t rank(const DMat<RT>& A) { DMatLinAlg<RT> LUdecomp(A); return LUdecomp.rank(); }
inline void determinant(const DMat<RT>& A, typename RT::ElementType& result) { DMatLinAlg<RT> LUdecomp(A); LUdecomp.determinant(result); }
void BoxChemStep(int i, int j, int k, long dt, const Vector *sunpos, double *photorate) { double f[MAXSUBST], vv[MAXSUBST], fact, err, origh2o; int indx[MAXSUBST], il, jl, nit; ProductionDesc *p; BOOL repeatit = FALSE; gli.i = i; gli.j = j; gli.k = k; gli.loc = k*layer+i*row+j; origh2o = g[HUMIDITY][gli.loc]; g[HUMIDITY][gli.loc] *= 1.608e9; CalcRateConstants(AbsoluteTemp(g[TEMP][gli.loc], pp[k], origh2o), dt, density[k], pp[k], sunpos->z, photorate); for (il = nsubst; il--; ) { /* if (CONZ(subst[il].subs) < 0.) printf("Warning: Substance %s got negative: %le\n", subst[il].name, CONZ(subst[il].subs)); */ if (CONZ(subst[il].subs) < 1.e-30) /* can't really handle such small concentrations */ CONZ(subst[il].subs) = 0.; } CalcRates(); for (il = nsubst; il--; ) { subst[il].oldc = CONZ(subst[il].subs); subst[il].take_as_fast = 0; } /* CalcSlowSubst(); Aenderung am 17.9.97! */ do { nit = 0; while (1) { jcb = CalculateJacobian(jcb); err = 0.; for (il = nfast; il--; ) { err += fabs((f[il] = CONZ(fast[il]->subs) - fast[il]->dcdt - fast[il]->oldc) / (CONZ(fast[il]->subs) > 1.e-7 ? CONZ(fast[il]->subs) : 1.)); } if (!repeatit && err < 1.e-5) break; if (++nit > 500) { printf("Chemistry is not converging at point %i/%i/%i\n", i, j, k); PrintConcentrations(); PrintRates(REACTION_RATES); break; } if (LUdecomp(nfast, jcb, indx, &fact, vv)) { printf("Matrix is singular (in ChemicalTimeStep) at point %d/%d/%d!\n", i, j, k); plausible = FALSE; return; } /* if (i == 10 && j == 4 && k == 1) PrintRates(REACTION_RATES); PrintMatrix(nfast, jcb, f); */ LUbackSub(nfast, jcb, indx, f); repeatit = 0; for (il = nfast; il--; ) { CONZ(fast[il]->subs) -= f[il]; if (CONZ(fast[il]->subs) < 0.) { /* printf("Warning: Substance %s got negative: %le\n", fast[il]->name, CONZ(fast[il]->subs)); */ CONZ(fast[il]->subs) = 0.; repeatit = 1; } } } repeatit = 0; CalcSlowSubst(); for (il = nfast; il--; ) { if (!fast[il]->oldc || fabs(CONZ(fast[il]->subs) - fast[il]->oldc) < 0.1 * fast[il]->oldc) { fast[il]->take_as_fast = 0; } } for (il = nslow; il--; ) { if (CONZ(slow[il]->subs) < 0.) { slow[il]->take_as_fast = repeatit = 1; } } if (repeatit) { printf("repeating chemistry at point %i/%i/%i\n", i, j, k); CalcRates(); } } while (repeatit); for (p = prodd; p; p = p->next) p->pps[gli.loc] = (CONZ(p->subs) - subst[p->subs - SUBS + 1].oldc) / (double)dt; g[HUMIDITY][k*layer+i*row+j] = origh2o; }