void AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::CalculateInverseJacobian(c_matrix<double, SPACE_DIM, ELEMENT_DIM>& rJacobian, double& rJacobianDeterminant, c_matrix<double, ELEMENT_DIM, SPACE_DIM>& rInverseJacobian) { assert(ELEMENT_DIM <= SPACE_DIM); CalculateJacobian(rJacobian, rJacobianDeterminant); // CalculateJacobian should make sure that the determinant is not close to zero (or, in fact, negative) assert(rJacobianDeterminant > 0.0); rInverseJacobian = Inverse(rJacobian); }
AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::AbstractTetrahedralElement(unsigned index, const std::vector<Node<SPACE_DIM>*>& rNodes) : AbstractElement<ELEMENT_DIM, SPACE_DIM>(index, rNodes) { // Sanity checking unsigned num_vectices = ELEMENT_DIM+1; double det; if (SPACE_DIM == ELEMENT_DIM) { // This is so we know it's the first time of asking // Create Jacobian c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacobian; try { CalculateJacobian(jacobian, det); } catch (Exception) { // if the Jacobian is negative the orientation of the element is probably // wrong, so swap the last two nodes around. this->mNodes[num_vectices-1] = rNodes[num_vectices-2]; this->mNodes[num_vectices-2] = rNodes[num_vectices-1]; CalculateJacobian(jacobian, det); // If determinant < 0 then element nodes are listed clockwise. // We want them anticlockwise. assert(det > 0.0); } } else { //This is not a full-dimensional element c_vector<double, SPACE_DIM> weighted_direction; CalculateWeightedDirection(weighted_direction, det); } }
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; }