Esempio n. 1
0
bool inflating_gauss_seidel(const IntervalMatrix& A, const IntervalVector& b, IntervalVector& x, double min_dist, double mu_max) {
	int n=(A.nb_rows());
	assert(n == (A.nb_cols()));
	assert(n == (x.size()) && n == (b.size()));
	assert(min_dist>0);
	//cout << " ====== inflating Gauss-Seidel ========= " << endl;
	double red;
	IntervalVector xold(n);
	Interval proj;
	double d=DBL_MAX; // Hausdorff distances between 2 iterations
	double dold;
	double mu; // ratio of dist(x_k,x_{k-1)) / dist(x_{k-1},x_{k-2}).
	do {
		dold = d;
		xold = x;
		for (int i=0; i<n; i++) {
			proj = b[i];
			for (int j=0; j<n; j++)	if (j!=i) proj -= A[i][j]*x[j];
			x[i] = proj/A[i][i];
		}
		d=distance(xold,x);
		mu=d/dold;
		//cout << "  x=" << x << " d=" << d << " mu=" << mu << endl;
	} while (mu<mu_max && d>min_dist);
	//cout << " ======================================= " << endl;
	return (mu<mu_max);

}
Esempio n. 2
0
static void gmshLineSearch(void (*func)(std::vector<double> &x, double &Obj,
                                        bool needGrad,
                                        std::vector<double> &gradObj,
                                        void *), // the function
                           void *data, // eventual data
                           std::vector<double> &x, // variables
                           std::vector<double> &p, // search direction
                           std::vector<double> &g, // gradient
                           double &f, double stpmax, int &check)
{
  int i;
  double alam, alam2 = 1., alamin, f2 = 0., fold2 = 0., rhs1, rhs2, temp,
               tmplam = 0.;

  const double ALF = 1.e-4;
  const double TOLX = 1.0e-9;

  std::vector<double> xold(x), grad(x);
  double fold;
  (*func)(xold, fold, false, grad, data);

  check = 0;
  int n = x.size();
  double norm = _norm(p);
  if(norm > stpmax) scale(p, stpmax / norm);
  double slope = 0.0;
  for(i = 0; i < n; i++) slope += g[i] * p[i];
  double test = 0.0;
  for(i = 0; i < n; i++) {
    temp = fabs(p[i]) / std::max(fabs(xold[i]), 1.0);
    if(temp > test) test = temp;
  }

  alamin = TOLX / test;
  alam = 1.;

  while(1) {
    for(i = 0; i < n; i++) x[i] = xold[i] + alam * p[i];
    (*func)(x, f, false, grad, data);
    if(f > 1.e280)
      alam *= .5;
    else
      break;
  }

  while(1) {
    for(i = 0; i < n; i++) x[i] = xold[i] + alam * p[i];
    (*func)(x, f, false, grad, data);

    //    printf("alam = %12.5E alamin = %12.5E f = %12.5E fold = %12.5E slope
    //    %12.5E stuff %12.5E\n",alam,alamin,f,fold, slope,  ALF * alam *
    //    slope);

    //    f = (*func)(x, data);
    if(alam < alamin) {
      for(i = 0; i < n; i++) x[i] = xold[i];
      check = 1;
      return;
    }
    else if(f <= fold + ALF * alam * slope)
      return;
    else {
      if(alam == 1.0)
        tmplam = -slope / (2.0 * (f - fold - slope));
      else {
        rhs1 = f - fold - alam * slope;
        rhs2 = f2 - fold2 - alam2 * slope;
        const double a =
          (rhs1 / (alam * alam) - rhs2 / (alam2 * alam2)) / (alam - alam2);
        const double b =
          (-alam2 * rhs1 / (alam * alam) + alam * rhs2 / (alam2 * alam2)) /
          (alam - alam2);
        if(a == 0.0)
          tmplam = -slope / (2.0 * b);
        else {
          const double disc = b * b - 3.0 * a * slope;
          if(disc < 0.0)
            Msg::Error("Roundoff problem in gmshLineSearch.");
          else
            tmplam = (-b + sqrt(disc)) / (3.0 * a);
        }
        if(tmplam > 0.5 * alam) tmplam = 0.5 * alam;
      }
    }
    alam2 = alam;
    f2 = f;
    fold2 = fold;
    alam = std::max(tmplam, 0.1 * alam);
  }
}
Esempio n. 3
0
    /* Run a simulation of heat diffusion of object o using Jacobi iteration and
	 * backwards euler discretization.
     *
     * @param ts Number of timesteps to simulate
     * @param dt Duration of each time step (s)
     * @param bs Boundary handling style. Options are:
     *              CONSTANT: boundary cells are set to `v` and never changed
     *              PERIODIC: boundary cells wrap around the object to take on
     *                        the temperature value on the opposite side.
     * @param v Value to use for CONSTANT boundary handling style
     * @param S Time independent source term to be added at each timestep
     * @param callback function to call periodically during the simulation to
     *                 provide feedback to the caller and test whether to halt
     *                 the simulation early.
     * @param callback_interval Number of timesteps between each callback
     */
    void jacobi(size_t ts,
                double dt,
                boundary_style bs, 
                double v,
                const object1d& S,
                std::function<bool(const object1d&,size_t ts)> callback,
                size_t callback_interval) const
    {
        double dx = m_lx / m_nx;
        double C = m_alpha*dt/(pow(dx,2));
        size_t nx = m_nx;
		
		object1d xold(m_lx,nx,m_alpha);
		object1d xcur(m_lx,nx,m_alpha);
		object1d xnew(m_lx,nx,m_alpha);
		
		// load initial values
		xold = *this;
		xcur = xold;

        size_t t;
		size_t MAX_ITER = 1000;
        double EPSILON = 1e-6;

		double C2 = C/(2*C+1);
		double C3 = 1/(2*C+1);

		int iter = 0;

		for (t = 0; t < ts; t++) {
			if (t%callback_interval == 0) {
                if (!callback(xcur,t)) {
                    break;
                }
            }
			
			size_t i = 0;
			for (i = 0; i < MAX_ITER; i++) {
				xnew[0] = C2*((bs == CONSTANT ? v : xcur[nx-1]) + xcur[1]) + C3*xold[0];
				for (size_t x = 1; x < nx-1; x++) {
					xnew[x] = C2*(xcur[x-1] + xcur[x+1]) + C3*xold[x];
				}
				xnew[nx-1] = C2*(xcur[nx-1] + (bs == CONSTANT ? v : xcur[0])) + C3*xold[nx-1];
				
				if (xcur.mean_abs_diff(xnew) < EPSILON) {
					break;
				}
				xcur = xnew;
			}
			iter += i;
			
			for (size_t x = 0; x < nx; x++) {
				xcur[x] += S[x]*dt;
			}

			xold = xcur;
        }

		std::cout << "average iterations: " << (iter/t) << std::endl;
        callback(xcur,t);
	}