Bool_t TMatlab::EvalString(const char* va_(fmt), ...) { #ifdef HAVE_MATLAB char buf[1024]; if (!fEngine) return 0; va_list ap; va_start(ap,va_(fmt)); vsprintf(buf, fmt, ap); return ((fEvalReturn=engEvalString((Engine*)fEngine,buf)) == 0); #else return kFALSE; #endif }
Bool_t TMatlab::Eval(const char* va_(fmt), ...) { #ifdef HAVE_MATLAB char buf[1024]; if (!fEngine) return 0; va_list ap; va_start(ap,va_(fmt)); vsprintf(buf, fmt, ap); if (!fOutputBuffer) OutputBuffer(); fEvalReturn = engEvalString((Engine*)fEngine,buf); cout << fOutputBuffer+2 << endl; return (fEvalReturn == 0); #else return kFALSE; #endif }
void MethodGear<ODESystemKernel>::ConvergenceRate() { // In case of too much large error or convergence failure if (iterErrorFailure_ > 0 || iterConvergenceFailure_ > 0) iterConvergenceRate_ = 0; // If the correction was find easily, with only a single iteration, // we do not need to apply any correction to the algorithm if (iterConvergence_ <= 1) return; vb_ = v_[0] - z_[0]; this->JacobianTimesVector(vb_, &va_); va_ *= h_; va_ += z_[1]; va_ = v_[1] - va_; #if defined(__clang__) double normd = 0.; for (unsigned int i=0;i<va_.size();i++) normd += std::fabs(va_(i)); double normf = 0.; for (unsigned int i=0;i<v_[1].size();i++) normf += std::fabs(v_[1](i)); #else const double normd = va_.lpNorm<1>(); const double normf = v_[1].lpNorm<1>(); #endif // If more than 2 iterations were needed and the normd is much larged than the normf, // it is better to reduce the step and reduce the order if (normd > 3.*normf + .1 && iterConvergence_ > 2) { // Better to update the Jacobian matrix if (numberOfSteps_ > stepOfLastJacobian_ + MAX_ITERATIONS_JACOBIAN / 10) if (jacobianType_ != JACOBIAN_TYPE_CONST) jacobianStatus_ = JACOBIAN_STATUS_HAS_TO_BE_CHANGED; // The step is halved hScale_ = 0.5; odeHStatus_ = H_STATUS_DECREASED; hNextStep_ = h_*hScale_; numberOfDecreasedSteps_++; // The order is reduced if (p_ > 1) { orderInNextStep_ = p_ - 1; odeOrderStatus_ = ORDER_STATUS_DECREASED; } iterConvergenceRate_ = 0; iterConvergenceFailure_ = 1; return; } // If the normd is not so larger than the normf if (normd > normf + 0.1) { // The iterConvergenceRate_ is increased only when we are here iterConvergenceRate_++; // The step is decreased by a small factor if (iterConvergenceRate_ >= 5) { hScale_ = 0.8; odeHStatus_ = H_STATUS_DECREASED; hNextStep_ = h_*hScale_; numberOfDecreasedSteps_++; iterConvergenceRate_ = 0; iterConvergenceFailure_ = 1; } if (jacobianType_ == JACOBIAN_TYPE_CONST) return; // Better to re-estimate the Jacobian matrix if (numberOfSteps_ > stepOfLastJacobian_ + MAX_ITERATIONS_JACOBIAN / 10 && iterConvergence_ > 2) { jacobianStatus_ = JACOBIAN_STATUS_HAS_TO_BE_CHANGED; iterConvergenceRate_ = 0; iterConvergenceFailure_ = 1; } } }
unsigned int MethodGear<ODESystemKernel>::FindCorrection(const double t, const Eigen::VectorXd& errorWeights) { // Current solution to be updated vb_ = v_[0]; // Check Constraints CheckConstraints(vb_); // Call the equations this->Equations(vb_, t, f_); numberOfFunctionCalls_++; // Force recalculation of Jacobian matrix (every maxIterationsJacobian_) if (numberOfSteps_ >= stepOfLastJacobian_ + maxIterationsJacobian_) jacobianStatus_ = JACOBIAN_STATUS_HAS_TO_BE_CHANGED; if (jacobianStatus_ == JACOBIAN_STATUS_HAS_TO_BE_CHANGED) { // The Jacobian is evaluated at the current step stepOfLastJacobian_ = numberOfSteps_; // Evaluation of the Jacobian matrix switch (jacobianType_) { case JACOBIAN_TYPE_CONST: jacobianStatus_ = JACOBIAN_STATUS_OK; break; case JACOBIAN_TYPE_USERDEFINED: jacobianStatus_ = JACOBIAN_STATUS_MODIFIED; this->UserDefinedJacobian(vb_, t); numberOfJacobians_++; factorizationStatus_ = MATRIX_HAS_TO_BE_FACTORIZED; break; case JACOBIAN_TYPE_NUMERICAL: jacobianStatus_ = JACOBIAN_STATUS_MODIFIED; this->NumericalJacobian(vb_, t, f_, h_, errorWeights, max_constraints_, max_values_); numberOfJacobians_++; factorizationStatus_ = MATRIX_HAS_TO_BE_FACTORIZED; break; } } // The hr0 value is used to build the G matrix (see Eq. 29.214) const double hr0 = h_*r_[0](p_ - 1); // If the order was changed, the matrix is factorized (of course!) if (factorizationStatus_ == MATRIX_FACTORIZED) { if (iterOrder_ == 0) factorizationStatus_ = MATRIX_HAS_TO_BE_FACTORIZED; } // The matrix is assembled and factorized if (factorizationStatus_ == MATRIX_HAS_TO_BE_FACTORIZED) { stepOfLastFactorization_ = numberOfSteps_; numberOfMatrixFactorizations_++; this->BuildAndFactorizeMatrixG(hr0); factorizationStatus_ = MATRIX_FACTORIZED; } // The firs iteration of the Newton's method is performed // The first guess value is assumed b=0, which means that the following linear system is solved: G*d = -v1+h*f // The solution d, since b=0 on first guess, is equal to the new b { deltab_ = f_*h_; deltab_ -= v_[1]; this->SolveLinearSystem(deltab_); numberOfLinearSystemSolutions_++; b_ = deltab_; } // Newton's iterations double oldCorrectionControl; for (unsigned int k = 1; k <= maxConvergenceIterations_; k++) { // Estimation of the error const double correctionControl = r_[0](p_ - 1)*OpenSMOKE::ErrorControl(deltab_, errorWeights); // If the error is sufficiently small, the convergence is ok if (correctionControl < 1.) { convergenceStatus_ = CONVERGENCE_STATUS_OK; return k; } // If the new error is 2 times larger than the previous one, it is better to stop the Newton's method // and try to restart with a smaller step if (k > 1 && correctionControl > 2.*oldCorrectionControl) { convergenceStatus_ = CONVERGENCE_STATUS_FAILURE; return k; } // Store the error oldCorrectionControl = correctionControl; // Update the solution by adding the vector b: v0 = v0+r0*b va_ = b_*r_[0](p_ - 1); va_ += v_[0]; // Check constraints for minimum and maximum values { // Minimum constraints if (min_constraints_ == true) { for (unsigned int j = 0; j < this->ne_; j++) if (va_(j) < min_values_(j)) { va_(j) = min_values_(j); b_(j) = (min_values_(j) - z_[0](j)) / r_[0](p_ - 1); } } // Maximum constraints if (max_constraints_ == true) { for (unsigned int j = 0; j < this->ne_; j++) if (va_(j) > max_values_(j)) { va_(j) = max_values_(j); b_(j) = (max_values_(j) - z_[0](j)) / r_[0](p_ - 1); } } } // Call the equations this->Equations(va_, t, f_); numberOfFunctionCalls_++; // Apply the Newton's iteration { deltab_ = f_*h_; deltab_ -= v_[1]; deltab_ -= b_; this->SolveLinearSystem(deltab_); numberOfLinearSystemSolutions_++; b_ += deltab_; } } convergenceStatus_ = CONVERGENCE_STATUS_FAILURE; return maxConvergenceIterations_; }