void Foam::SIBS::solve ( const ODE& ode, scalar& x, scalarField& y, scalarField& dydx, const scalar eps, const scalarField& yScale, const scalar hTry, scalar& hDid, scalar& hNext ) const { bool exitflag = false; if (eps != epsOld_) { hNext = xNew_ = -GREAT; scalar eps1 = safe1*eps; a_[0] = nSeq_[0] + 1; for (register label k=0; k<kMaxX_; k++) { a_[k + 1] = a_[k] + nSeq_[k + 1]; } for (register label iq = 1; iq<kMaxX_; iq++) { for (register label k=0; k<iq; k++) { alpha_[k][iq] = pow(eps1, (a_[k + 1] - a_[iq + 1]) /((a_[iq + 1] - a_[0] + 1.0)*(2*k + 3))); } } epsOld_ = eps; a_[0] += n_; for (register label k=0; k<kMaxX_; k++) { a_[k + 1] = a_[k] + nSeq_[k + 1]; } for (kOpt_ = 1; kOpt_<kMaxX_ - 1; kOpt_++) { if (a_[kOpt_ + 1] > a_[kOpt_]*alpha_[kOpt_ - 1][kOpt_]) { break; } } kMax_ = kOpt_; } label k=0; scalar h = hTry; yTemp_ = y; ode.jacobian(x, y, dfdx_, dfdy_); if (x != xNew_ || h != hNext) { first_ = 1; kOpt_ = kMax_; } label km=0; label reduct=0; scalar maxErr = SMALL; for (;;) { scalar red = 1.0; for (k=0; k <= kMax_; k++) { xNew_ = x + h; if (xNew_ == x) { FatalErrorIn("ODES::SIBS") << "step size underflow" << exit(FatalError); } SIMPR(ode, x, yTemp_, dydx, dfdx_, dfdy_, h, nSeq_[k], ySeq_); scalar xest = sqr(h/nSeq_[k]); polyExtrapolate(k, xest, ySeq_, y, yErr_, x_p_, d_p_); if (k != 0) { maxErr = SMALL; for (register label i=0; i<n_; i++) { maxErr = max(maxErr, mag(yErr_[i]/yScale[i])); } maxErr /= eps; km = k - 1; err_[km] = pow(maxErr/safe1, 1.0/(2*km + 3)); } if (k != 0 && (k >= kOpt_ - 1 || first_)) { if (maxErr < 1.0) { exitflag = true; break; } if (k == kMax_ || k == kOpt_ + 1) { red = safe2/err_[km]; break; } else if (k == kOpt_ && alpha_[kOpt_ - 1][kOpt_] < err_[km]) { red = 1.0/err_[km]; break; } else if (kOpt_ == kMax_ && alpha_[km][kMax_ - 1] < err_[km]) { red = alpha_[km][kMax_ - 1]*safe2/err_[km]; break; } else if (alpha_[km][kOpt_] < err_[km]) { red = alpha_[km][kOpt_ - 1]/err_[km]; break; } } } if (exitflag) { break; } red = min(red, redMin); red = max(red, redMax); h *= red; reduct = 1; } x = xNew_; hDid = h; first_=0; scalar wrkmin = GREAT; scalar scale = 1.0; for (register label kk=0; kk<=km; kk++) { scalar fact = max(err_[kk], scaleMX); scalar work = fact*a_[kk + 1]; if (work < wrkmin) { scale = fact; wrkmin = work; kOpt_ = kk + 1; } } hNext = h/scale; if (kOpt_ >= k && kOpt_ != kMax_ && !reduct) { scalar fact = max(scale/alpha_[kOpt_ - 1][kOpt_], scaleMX); if (a_[kOpt_ + 1]*fact <= wrkmin) { hNext = h/fact; kOpt_++; } } }
void Foam::KRR4::solve ( const ODE& ode, scalar& x, scalarField& y, scalarField& dydx, const scalar eps, const scalarField& yScale, const scalar hTry, scalar& hDid, scalar& hNext ) const { scalar xTemp = x; yTemp_ = y; dydxTemp_ = dydx; ode.jacobian(xTemp, yTemp_, dfdx_, dfdy_); scalar h = hTry; for (register label jtry=0; jtry<maxtry; jtry++) { for (register label i=0; i<n_; i++) { for (register label j=0; j<n_; j++) { a_[i][j] = -dfdy_[i][j]; } a_[i][i] += 1.0/(gamma*h); } LUDecompose(a_, pivotIndices_); for (register label i=0; i<n_; i++) { g1_[i] = dydxTemp_[i] + h*c1X*dfdx_[i]; } LUBacksubstitute(a_, pivotIndices_, g1_); for (register label i=0; i<n_; i++) { y[i] = yTemp_[i] + a21*g1_[i]; } x = xTemp + a2X*h; ode.derivatives(x, y, dydx_); for (register label i=0; i<n_; i++) { g2_[i] = dydx_[i] + h*c2X*dfdx_[i] + c21*g1_[i]/h; } LUBacksubstitute(a_, pivotIndices_, g2_); for (register label i=0; i<n_; i++) { y[i] = yTemp_[i] + a31*g1_[i] + a32*g2_[i]; } x = xTemp + a3X*h; ode.derivatives(x, y, dydx_); for (register label i=0; i<n_; i++) { g3_[i] = dydx[i] + h*c3X*dfdx_[i] + (c31*g1_[i] + c32*g2_[i])/h; } LUBacksubstitute(a_, pivotIndices_, g3_); for (register label i=0; i<n_; i++) { g4_[i] = dydx_[i] + h*c4X*dfdx_[i] + (c41*g1_[i] + c42*g2_[i] + c43*g3_[i])/h; } LUBacksubstitute(a_, pivotIndices_, g4_); for (register label i=0; i<n_; i++) { y[i] = yTemp_[i] + b1*g1_[i] + b2*g2_[i] + b3*g3_[i] + b4*g4_[i]; yErr_[i] = e1*g1_[i] + e2*g2_[i] + e3*g3_[i] + e4*g4_[i]; } x = xTemp + h; if (x == xTemp) { FatalErrorIn("ODES::KRR4") << "stepsize not significant" << exit(FatalError); } scalar maxErr = 0.0; for (register label i=0; i<n_; i++) { maxErr = max(maxErr, mag(yErr_[i]/yScale[i])); } maxErr /= eps; if (maxErr <= 1.0) { hDid = h; hNext = (maxErr > errcon ? safety*h*pow(maxErr, pgrow) : grow*h); return; } else { hNext = safety*h*pow(maxErr, pshrink); h = (h >= 0.0 ? max(hNext, shrink*h) : min(hNext, shrink*h)); } } FatalErrorIn("ODES::KRR4") << "exceeded maxtry" << exit(FatalError); }