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); }
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); } }
/* 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); }