示例#1
0
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
}
示例#2
0
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
}
示例#3
0
	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;
			}
		}
	}
示例#4
0
	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_;
	}