bool IASIAM::Run(IAResult* r) //output { this->r = r; N = r->iagrid->get_N(); iagrid = r->iagrid; printf(" -------IASIAM: mu=%.3f, U=%.3f, T=%.3f, epsilon=%.3f -------\n", r->mu, U, T, epsilon); complex<double>* V = new complex<double>[1]; //----- initial guess ------// V[0] = r->mu0; //---------------------------// //------ SOLVE IASIAM ---------// double mu0inits [] = {0.0, 1.0, -1.0, -0.8, 2.0, 1.5, -1.5, 2.5, -2.5, -2.0, 0.05, 0.8, 0.1, -0.1, 0.3, -0.3, 0.5, -0.5, -0.05, 0.4, -0.4, 0.6, -0.6, 2.3, -2.3, 2.8, -2.8, 1.8, -1.8 }; bool failed = !UseBroydenFormu0; int c = 0; //printf("IASIAM: about to do mu0 search\n"); while ( UseBroydenFormu0 and ( UseBroyden<IASIAM>(1, MAX_ITS, Accr, &IASIAM::SolveSiam, this, V) != 1 ) ) { c++; //printf("IASIAM: passed the first broyden use\n"); if ( (c >= max_tries) or (c >= sizeof(mu0inits)/sizeof(double) - 1 ) ) { printf("\n\n\n\n==== IASIAM ERROR ====: Broyden mu0 search failed to converge. Now switching to amoeba ...\n\n\n\n"); failed = true; break; } V[0] = mu0inits[c]; printf("==================== ====================== ========== TRYING new mu0 int!!! c = %d, mu0init = %f\n\n\n",c, mu0inits[c]); }; if ( (failed) or (abs(V[0])>5.0) ) { V[0] = mu0inits[0]; Amoeba(Accr, V, &IASIAM::SolveSiam); } delete [] V; //----------------------------// r->mu0 = mu0; printf(" IASIAM: mu0 = %f, n = %f\n",r->mu0, r->n); return false; }
double AmoebaMinimizer::Minimize(double ftol) { int i, ilo, ihi, inhi, m, nvertex = point.dim + 1; double rtol, ysave, ytry; if (point.dim == 0) return fmin = f(point); // Setup the simplex, and evaluate f at each vortex for (i=0; i < point.dim; i++) { simplex[i] = point; simplex[i].Add (directions[i]); y[i] = f(simplex[i]); if (y[i] < fmin) fmin = y[i]; } simplex[nvertex - 1] = point; y[nvertex - 1] = f(simplex[nvertex - 1]); if (y[nvertex - 1] < fmin) fmin = y[nvertex - 1]; cycleCount = nvertex; // Calculate psum for (psum = simplex[0], m = 1; m < nvertex; m++) psum.Add(simplex[m]); while (true) { // First we must determine which is the highest, next // highest and lowest point in the simplex ihi = y[0] > y[1] ? (ilo = inhi = 1, 0) : (ilo = inhi = 0, 1); for (i = 2; i < nvertex; i++) { if (y[i] <= y[ilo]) ilo = i; else if (y[i] > y[ihi]) { inhi = ihi; ihi = i; } else if (y[i] > y[inhi]) inhi = i; } // Compute the range from highest to lowest, return if satisfactory rtol = 2 * fabs(y[ihi] - y[ilo])/(fabs(y[ihi])+fabs(y[ilo])+ZEPS); if (rtol < ftol) { point = simplex[ilo]; return fmin = y[ilo]; } if (cycleCount > cycleMax) error("Amoeba.Minimize - Couldn't converge in %d cycles", cycleMax); // begin a new iteration... // first extrapolate by a factor of -1 through the face of the simplex // (reflection) cycleCount += 2; ytry = Amoeba(ihi, -1.0); if (ytry <= y[ilo]) // Better than previous best, keep going Amoeba(ihi, 2.0); else if (ytry >= y[inhi]) { // still worse than next highest point, so do a one- // dimensional contraction to find an intermediate // lower point ysave = y[ihi]; ytry = Amoeba(ihi, 0.5); if (ytry >= ysave) { // Can't get rid of that high point // Better to contract around lowest point for (i = 0; i < nvertex; i++) if (i != ilo) { simplex[i].Add(simplex[ilo]); simplex[i].Multiply(0.5); y[i] = f(simplex[i]); } cycleCount += point.dim; // keep track of function evaluations for (psum = simplex[0], m = 1; m < nvertex; m++) psum.Add(simplex[m]); } } else cycleCount --; } }
double SAMinimizer::MinimizeLoop(double ) { int i, ihi, ilo, m, nvertex = point.dim + 1; double ylo, ynhi, ysave, yt, ytry; // Calculate psum for (psum = simplex[0], m = 1; m < nvertex; m++) psum.Add(simplex[m]); while (true) { // Determine which point is highest (worst), // next highest, and lowest (best) // ilo = 0; ihi = 1; // whenever we look at a vertex it gets a // random 'thermal' fluctuation ynhi = ylo = y[0] - T * log(rand->Next()); yhi = y[1] - T * log(rand->Next()); if (ylo > yhi) { ihi = 1; ilo = 0; ynhi = yhi; yhi = ylo; ylo = ynhi; } for (i = 2; i < nvertex; i++) { yt = y[i] - T * log(rand->Next()); if (yt <= ylo) { ilo = i; ylo = yt; } else if (yt > yhi) { ynhi = yhi; ihi = i; yhi = yt; } else if (yt > ynhi) ynhi = yt; } // Compute the fractional range from highest to lowest // and return if satisfactory // rtol = 2.0 * (yhi - ylo) / (fabs(yhi) + fabs(ylo)); // if ((rtol < ftol) || (iter < 0)) if (iter < 0) { // put best point and value in slot 1 before return y.Swap(0, ilo); simplex.SwapRows(0, ilo); return fmin; } // Begin a new iteration: // First. Extrapolate by a factor -1 through the face of the simplex // across from the high point (ie. reflect from the high point) iter -= 2; ytry = Amoeba(ihi, -1.0); if (ytry < ylo) // gives a better result than the best point, so go even further Amoeba(ihi, 2.0); else if (ytry >= ynhi) { // the reflected point is worse than the second highest so // look for an intermediate (do a one-dimensional contration) ysave = yhi; ytry = Amoeba(ihi, 0.5); if (ytry >= ysave) { // Can't get rid of worst point, so contract around // lowest point for (i = 0; i < nvertex; i++) if ( i != ilo ) { simplex[i].Add(simplex[ilo]); simplex[i].Multiply(0.5); y[i] = f(simplex[i]); if (y[i] <= fmin) { point = simplex[i]; fmin = y[i]; } } // Calculate psum for (psum = simplex[0], m = 1; m < nvertex; m++) psum.Add(simplex[m]); iter -= point.dim; } } else iter++; // correct evaluation count } }
bool IASIAM::Run_CHM(IAResult* r) //output { this->r = r; N = r->iagrid->get_N(); iagrid = r->iagrid; epsilon = 0; printf(" ------- IASIAM for CHM: n=%.3f, U=%.3f, T=%.3f, epsilon=%.3f -------\n", r->n, U, T, epsilon); //----------------- CALCULATION ----------------------// if (PHSymmetricCase) { mu0 = 0.0; get_G0(); } else { complex<double>* V = new complex<double>[1]; //------initial guess---------// V[0] = r->mu0; //initial guess is always the last mu0. in first DMFT iteration it is 0 //---------------------------// printf(" IASIAM: about to calc mu0. at the moment: mu0 = %.3f mu=%.3f\n",r->mu0, r->mu); double initGuesses [] = {-1.0, 1.0, 0.3, -0.3, 0.1, -0.1, -0.8, 0.8, -0.6, 0.6, -0.7, 0.7, -3.0, 3.0, 0.9, -0.9, 0.05, -0.05, 0.5, -0.5, 0.2, -0.2, 2.0, -2.0}; bool converged = false; int i; for (i=0; ( (i<sizeof(initGuesses)/sizeof(double)) and (i<max_tries) ); i++) { printf("------ IASIAM: trying with init guess: %f\n",real(V[0])); converged = UseBroyden<IASIAM>(1, 50, 1e-8, &IASIAM::get_G0, this, V); if (converged) break; else V[0] = initGuesses[i]; } if ((i==max_tries)and(!converged)) { V[0] = initGuesses[0]; Amoeba(Accr, V, &IASIAM::get_G0); } delete [] V; } r->mu0 = mu0; //PrintFunc("G0", N, r->G0, r->omega); printf(" mu0 = %f\n", mu0); fft->FtoT(r->G0, r->G0_tau); get_SOCSigma_tau(); fft->TtoF(r->SOCSigma_tau, r->SOCSigma); if (PHSymmetricCase) { r->mu = 0.5*U; r->n=0.5; get_G(); } else { complex<double>* V = new complex<double>[1]; V[0] = r->mu; double initGuesses [] = {-1.0, 1.0, -0.8, 0.8, -0.6, 0.6, 0.2, -0.2, 2.0, -2.0}; bool converged = false; int i; for (i=0; ( (i<sizeof(initGuesses)/sizeof(double)) and (i<max_tries) ); i++) { printf("------ IASIAM: trying with init guess: %f\n",real(V[0])); converged = UseBroyden<IASIAM>(1, MAX_ITS, 1e-8, &IASIAM::get_G, this, V); if (converged){ break; } else V[0] = initGuesses[i]; } if ((i==max_tries)and(!converged)) { V[0] = initGuesses[0]; Amoeba(Accr, V, &IASIAM::get_G); } delete [] V; } printf(" mu = %f\n", r->mu); //-----------------------------------------------------// return false; }