46 #ifndef _NonLinearLineSearch_H_ 47 #define _NonLinearLineSearch_H_ 1
85 template <
class Fct,
class VectorType>
91 if ( verboseLevel > 0 )
93 std::cout <<
"Parabolic line search ..." << std::endl;
95 const Real sigma0 = 0.1;
96 const Real sigma1 = 0.5;
97 const Real alpha = 1.e-4;
98 const Int maxIterations = 50;
100 static VectorType S_solCurrent = sol;
101 Int iterNonLinearLineSearch;
102 Real lambdaCurrent, lambdaOld, normResTest, res2, resTest2, resTestOld2, c1, c2;
104 res2 = normRes * normRes;
106 lambdaCurrent = lambda;
108 sol += lambda * step;
109 f.evalResidual ( residual, sol, iter );
110 normResTest = residual.normInf();
111 resTest2 = normResTest * normResTest;
112 resTestOld2 = resTest2;
113 iterNonLinearLineSearch = 0;
114 while ( normResTest >= ( 1 - alpha * lambda ) * normRes )
116 iterNonLinearLineSearch++;
118 c2 = lambdaOld * ( resTest2 - res2 ) - lambdaCurrent * ( resTestOld2 - res2 );
121 lambda = sigma1 * lambdaCurrent;
125 c1 = lambdaCurrent * lambdaCurrent * ( resTestOld2 - res2 )
126 - lambdaOld * lambdaOld * ( resTest2 - res2 );
127 lambda = -c1 * .5 / c2;
128 if ( lambda < sigma0 * lambdaCurrent )
130 lambda = sigma0 * lambdaCurrent;
132 if ( lambda > sigma1 * lambdaCurrent )
134 lambda = sigma1 * lambdaCurrent;
137 if ( verboseLevel > 0 )
138 std::cout <<
"--- line search " << iterNonLinearLineSearch <<
" : residual test = " 139 << normResTest <<
", reduction = " << lambda << std::endl;
142 sol += lambda * step;
143 lambdaOld = lambdaCurrent;
144 lambdaCurrent = lambda;
146 f.evalResidual ( residual, sol, iter );
147 normResTest = residual.normInf();
148 resTestOld2 = resTest2;
149 resTest2 = normResTest * normResTest;
150 if ( iterNonLinearLineSearch > maxIterations )
152 if ( verboseLevel > 0 )
154 std::cout <<
"!!! Too many iterations in the line search algorithm" << std::endl;
159 normRes = normResTest;
160 if ( verboseLevel > 0 )
162 std::cout <<
"Parabolic line search: final residual = " << normRes << std::endl;
199 template <
class Fct,
class VectorType>
205 if ( verboseLevel > 0 )
207 std::cout <<
"Cubic line search ..." << std::endl;
210 const Real sigma0 = 0.1;
211 const Real sigma1 = 0.5;
212 const Real m1 = 0.25;
213 const Real m2 = 0.75;
214 const Int maxIterations = 50;
216 static VectorType S_solCurrent = sol;
218 bool firstTime =
true;
219 Real lambda2, lambdaOld, lambdaOld2, lambdaTemporary,
220 normResTest, f0, ftest, c, c11, c12, c21, c22, a, b, disc, g1, g2, gprev = 0;
222 f0 = 0.5 * normRes * normRes;
225 sol += lambda * step;
226 f.evalResidual ( residual, sol, iter );
227 normResTest = residual.normInf();
228 ftest = 0.5 * normResTest * normResTest;
230 while ( ftest < f0 + m2 * slope * lambda
231 && iterLinesearch < maxIterations )
236 sol += lambda * step;
237 if ( verboseLevel > 0 )
239 std::cout <<
"--- line search (extrapolation, Goldstein rule)" << std::endl;
241 f.evalResidual ( residual, sol, iter );
243 if ( verboseLevel > 0 )
244 std::cout <<
" line search iter : " << iterLinesearch <<
" residual test = " 245 << normResTest <<
", lambda = " << lambda << std::endl;
246 normResTest = residual.normInf();
247 ftest = 0.5 * normResTest * normResTest;
249 if ( iterLinesearch == maxIterations )
251 if ( verboseLevel > 0 )
253 std::cout <<
"line search: too many extrapolations" << std::endl;
258 while ( ftest > f0 + m1 * slope * lambda
259 && iterLinesearch < maxIterations )
263 lambda2 = lambda * lambda;
264 g1 = ftest - f0 - slope * lambda;
267 lambdaTemporary = - slope * lambda2 / ( 2. * g1 );
272 lambdaOld2 = lambdaOld * lambdaOld;
273 g2 = gprev - f0 - lambdaOld * slope;
274 c = 1. / ( lambda - lambdaOld );
276 c12 = -1. / lambdaOld2;
277 c21 = - lambdaOld / lambda2;
278 c22 = lambda / lambdaOld2;
279 a = c * ( c11 * g1 + c12 * g2 );
280 b = c * ( c21 * g1 + c22 * g2 );
281 disc = b * b - 3. * a * slope;
282 if ( ( std::fabs ( a ) > std::numeric_limits<Real>::min() ) &&
283 ( disc > std::numeric_limits<Real>::min() )
286 lambdaTemporary = ( - b + std::sqrt ( disc ) ) / ( 3. * a );
290 lambdaTemporary = slope * lambda2 / ( 2. * g1 ) ;
292 if ( lambdaTemporary >= sigma1 * lambda )
294 lambdaTemporary = sigma1 * lambda;
299 if ( lambdaTemporary < sigma0 * lambda )
305 lambda = lambdaTemporary;
309 sol += lambda * step;
310 if ( verboseLevel > 0 )
312 std::cout <<
"--- line search (cubic interpolation, Armijo rule)" << std::endl;
314 f.evalResidual ( residual, sol, iter );
315 normResTest = residual.normInf();
316 if ( verboseLevel > 0 )
317 std::cout <<
" line search iter : " << iterLinesearch <<
" residual test = " 318 << normResTest <<
", lambda = " << lambda << std::endl;
319 ftest = 0.5 * normResTest * normResTest;
321 if ( iterLinesearch == maxIterations )
323 if ( verboseLevel > 0 )
325 std::cout <<
"line search: too many interpolations" << std::endl;
329 normRes = normResTest;
330 if ( verboseLevel > 0 )
332 std::cout <<
"Parabolic line search: final residual = " << normRes << std::endl;
Int NonLinearLineSearchCubic(Fct &f, VectorType &residual, VectorType &sol, VectorType &step, Real &normRes, Real &lambda, Real &slope, UInt iter, UInt const verboseLevel=1)
Implementation of Line Search method with cubic interpolation.
int32_type Int
Generic integer data.
double Real
Generic real data.
Int NonLinearLineSearchParabolic(Fct &f, VectorType &residual, VectorType &sol, VectorType &step, Real &normRes, Real &lambda, UInt iter, UInt const verboseLevel=1)
Implementation of Line Search method with parabolic interpolation.
uint32_type UInt
generic unsigned integer (used mainly for addressing)