void Foam::SIBS::solve ( scalar& x, scalarField& y, scalarField& dydx, const scalar eps, const scalarField& yScale, const scalar hTry, scalar& hDid, scalar& hNext ) const { bool exitflag = false; const label nEqns = ode_.nEqns(); 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] += nEqns; 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(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<nEqns; 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::SIBS::solve ( scalar& x, scalarField& y, scalar& dxTry ) const { odes_.derivatives(x, y, dydx0_); scalar h = dxTry; bool exitflag = false; if (relTol_[0] != epsOld_) { dxTry = xNew_ = -GREAT; scalar eps1 = safe1*relTol_[0]; a_[0] = nSeq_[0] + 1; for (label k=0; k<kMaxX_; k++) { a_[k + 1] = a_[k] + nSeq_[k + 1]; } for (label iq = 1; iq<kMaxX_; iq++) { for (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_ = relTol_[0]; a_[0] += n_; for (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; yTemp_ = y; odes_.jacobian(x, y, dfdx_, dfdy_); if (x != xNew_ || h != dxTry) { 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) { FatalErrorInFunction << "step size underflow" << exit(FatalError); } SIMPR(x, yTemp_, dydx0_, 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 (label i=0; i<n_; i++) { maxErr = max ( maxErr, mag(yErr_[i])/(absTol_[i] + relTol_[i]*mag(yTemp_[i])) ); } 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_; first_ = 0; scalar wrkmin = GREAT; scalar scale = 1.0; for (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; } } dxTry = h/scale; if (kOpt_ >= k && kOpt_ != kMax_ && !reduct) { scalar fact = max(scale/alpha_[kOpt_ - 1][kOpt_], scaleMX); if (a_[kOpt_ + 1]*fact <= wrkmin) { dxTry = h/fact; kOpt_++; } } }