xref: /petsc/src/tao/unconstrained/impls/nls/nls.c (revision d71ae5a4db6382e7f06317b8d368875286fe9008)
1ba92ff59SBarry Smith #include <petsctaolinesearch.h>
21daac38eSTodd Munson #include <../src/tao/unconstrained/impls/nls/nlsimpl.h>
3a7e14dcfSSatish Balay 
4aaa7dc30SBarry Smith #include <petscksp.h>
5a7e14dcfSSatish Balay 
6a7e14dcfSSatish Balay #define NLS_INIT_CONSTANT      0
7a7e14dcfSSatish Balay #define NLS_INIT_DIRECTION     1
8a7e14dcfSSatish Balay #define NLS_INIT_INTERPOLATION 2
9a7e14dcfSSatish Balay #define NLS_INIT_TYPES         3
10a7e14dcfSSatish Balay 
11a7e14dcfSSatish Balay #define NLS_UPDATE_STEP          0
12a7e14dcfSSatish Balay #define NLS_UPDATE_REDUCTION     1
13a7e14dcfSSatish Balay #define NLS_UPDATE_INTERPOLATION 2
14a7e14dcfSSatish Balay #define NLS_UPDATE_TYPES         3
15a7e14dcfSSatish Balay 
1687f595a5SBarry Smith static const char *NLS_INIT[64] = {"constant", "direction", "interpolation"};
17a7e14dcfSSatish Balay 
1887f595a5SBarry Smith static const char *NLS_UPDATE[64] = {"step", "reduction", "interpolation"};
19a7e14dcfSSatish Balay 
201daac38eSTodd Munson /*
21a7e14dcfSSatish Balay  Implements Newton's Method with a line search approach for solving
22a7e14dcfSSatish Balay  unconstrained minimization problems.  A More'-Thuente line search
23a7e14dcfSSatish Balay  is used to guarantee that the bfgs preconditioner remains positive
24a7e14dcfSSatish Balay  definite.
25a7e14dcfSSatish Balay 
26a7e14dcfSSatish Balay  The method can shift the Hessian matrix.  The shifting procedure is
27a7e14dcfSSatish Balay  adapted from the PATH algorithm for solving complementarity
28a7e14dcfSSatish Balay  problems.
29a7e14dcfSSatish Balay 
30a7e14dcfSSatish Balay  The linear system solve should be done with a conjugate gradient
311daac38eSTodd Munson  method, although any method can be used.
321daac38eSTodd Munson */
33a7e14dcfSSatish Balay 
34a7e14dcfSSatish Balay #define NLS_NEWTON   0
35a7e14dcfSSatish Balay #define NLS_BFGS     1
360c51296cSAlp Dener #define NLS_GRADIENT 2
37a7e14dcfSSatish Balay 
38*d71ae5a4SJacob Faibussowitsch static PetscErrorCode TaoSolve_NLS(Tao tao)
39*d71ae5a4SJacob Faibussowitsch {
40a7e14dcfSSatish Balay   TAO_NLS                     *nlsP = (TAO_NLS *)tao->data;
411daac38eSTodd Munson   KSPType                      ksp_type;
420ad3a497SAlp Dener   PetscBool                    is_nash, is_stcg, is_gltr, is_bfgs, is_jacobi, is_symmetric, sym_set;
43a7e14dcfSSatish Balay   KSPConvergedReason           ksp_reason;
441daac38eSTodd Munson   PC                           pc;
451daac38eSTodd Munson   TaoLineSearchConvergedReason ls_reason;
46a7e14dcfSSatish Balay 
47a7e14dcfSSatish Balay   PetscReal fmin, ftrial, f_full, prered, actred, kappa, sigma;
48a7e14dcfSSatish Balay   PetscReal tau, tau_1, tau_2, tau_max, tau_min, max_radius;
49a7e14dcfSSatish Balay   PetscReal f, fold, gdx, gnorm, pert;
50a7e14dcfSSatish Balay   PetscReal step   = 1.0;
51a7e14dcfSSatish Balay   PetscReal norm_d = 0.0, e_min;
52a7e14dcfSSatish Balay 
53a7e14dcfSSatish Balay   PetscInt stepType;
54a7e14dcfSSatish Balay   PetscInt bfgsUpdates = 0;
55a7e14dcfSSatish Balay   PetscInt n, N, kspits;
56b4690188SBarry Smith   PetscInt needH = 1;
57a7e14dcfSSatish Balay 
58a7e14dcfSSatish Balay   PetscInt i_max = 5;
59a7e14dcfSSatish Balay   PetscInt j_max = 1;
60a7e14dcfSSatish Balay   PetscInt i, j;
61a7e14dcfSSatish Balay 
62a7e14dcfSSatish Balay   PetscFunctionBegin;
6348a46eb9SPierre Jolivet   if (tao->XL || tao->XU || tao->ops->computebounds) PetscCall(PetscInfo(tao, "WARNING: Variable bounds have been set but will be ignored by nls algorithm\n"));
64a7e14dcfSSatish Balay 
65a7e14dcfSSatish Balay   /* Initialized variables */
66a7e14dcfSSatish Balay   pert = nlsP->sval;
67a7e14dcfSSatish Balay 
682d9aa51bSJason Sarich   /* Number of times ksp stopped because of these reasons */
69a7e14dcfSSatish Balay   nlsP->ksp_atol = 0;
70a7e14dcfSSatish Balay   nlsP->ksp_rtol = 0;
71a7e14dcfSSatish Balay   nlsP->ksp_dtol = 0;
72a7e14dcfSSatish Balay   nlsP->ksp_ctol = 0;
73a7e14dcfSSatish Balay   nlsP->ksp_negc = 0;
74a7e14dcfSSatish Balay   nlsP->ksp_iter = 0;
75a7e14dcfSSatish Balay   nlsP->ksp_othr = 0;
76a7e14dcfSSatish Balay 
77a7e14dcfSSatish Balay   /* Initialize trust-region radius when using nash, stcg, or gltr
78ba7fe8fbSTodd Munson      Command automatically ignored for other methods
79ba7fe8fbSTodd Munson      Will be reset during the first iteration
80ba7fe8fbSTodd Munson   */
819566063dSJacob Faibussowitsch   PetscCall(KSPGetType(tao->ksp, &ksp_type));
829566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(ksp_type, KSPNASH, &is_nash));
839566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(ksp_type, KSPSTCG, &is_stcg));
849566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(ksp_type, KSPGLTR, &is_gltr));
851daac38eSTodd Munson 
869566063dSJacob Faibussowitsch   PetscCall(KSPCGSetRadius(tao->ksp, nlsP->max_radius));
87a7e14dcfSSatish Balay 
881daac38eSTodd Munson   if (is_nash || is_stcg || is_gltr) {
893c859ba3SBarry Smith     PetscCheck(tao->trust0 >= 0.0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Initial radius negative");
90a7e14dcfSSatish Balay     tao->trust = tao->trust0;
91a7e14dcfSSatish Balay     tao->trust = PetscMax(tao->trust, nlsP->min_radius);
92a7e14dcfSSatish Balay     tao->trust = PetscMin(tao->trust, nlsP->max_radius);
93a7e14dcfSSatish Balay   }
94a7e14dcfSSatish Balay 
95a7e14dcfSSatish Balay   /* Check convergence criteria */
969566063dSJacob Faibussowitsch   PetscCall(TaoComputeObjectiveAndGradient(tao, tao->solution, &f, tao->gradient));
979566063dSJacob Faibussowitsch   PetscCall(TaoGradientNorm(tao, tao->gradient, NORM_2, &gnorm));
983c859ba3SBarry Smith   PetscCheck(!PetscIsInfOrNanReal(f) && !PetscIsInfOrNanReal(gnorm), PetscObjectComm((PetscObject)tao), PETSC_ERR_USER, "User provided compute function generated Inf or NaN");
99a7e14dcfSSatish Balay 
1003ecd9318SAlp Dener   tao->reason = TAO_CONTINUE_ITERATING;
1019566063dSJacob Faibussowitsch   PetscCall(TaoLogConvergenceHistory(tao, f, gnorm, 0.0, tao->ksp_its));
1029566063dSJacob Faibussowitsch   PetscCall(TaoMonitor(tao, tao->niter, f, gnorm, 0.0, step));
103dbbe0bcdSBarry Smith   PetscUseTypeMethod(tao, convergencetest, tao->cnvP);
1043ecd9318SAlp Dener   if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0);
105a7e14dcfSSatish Balay 
1060c51296cSAlp Dener   /* Allocate the vectors needed for the BFGS approximation */
1079566063dSJacob Faibussowitsch   PetscCall(KSPGetPC(tao->ksp, &pc));
1089566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCLMVM, &is_bfgs));
1099566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCJACOBI, &is_jacobi));
1100c51296cSAlp Dener   if (is_bfgs) {
1110c51296cSAlp Dener     nlsP->bfgs_pre = pc;
1129566063dSJacob Faibussowitsch     PetscCall(PCLMVMGetMatLMVM(nlsP->bfgs_pre, &nlsP->M));
1139566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(tao->solution, &n));
1149566063dSJacob Faibussowitsch     PetscCall(VecGetSize(tao->solution, &N));
1159566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(nlsP->M, n, n, N, N));
1169566063dSJacob Faibussowitsch     PetscCall(MatLMVMAllocate(nlsP->M, tao->solution, tao->gradient));
1179566063dSJacob Faibussowitsch     PetscCall(MatIsSymmetricKnown(nlsP->M, &sym_set, &is_symmetric));
1183c859ba3SBarry Smith     PetscCheck(sym_set && is_symmetric, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "LMVM matrix in the LMVM preconditioner must be symmetric.");
1191baa6e33SBarry Smith   } else if (is_jacobi) PetscCall(PCJacobiSetUseAbs(pc, PETSC_TRUE));
120a7e14dcfSSatish Balay 
121a7e14dcfSSatish Balay   /* Initialize trust-region radius.  The initialization is only performed
122a7e14dcfSSatish Balay      when we are using Nash, Steihaug-Toint or the Generalized Lanczos method. */
1231daac38eSTodd Munson   if (is_nash || is_stcg || is_gltr) {
124a7e14dcfSSatish Balay     switch (nlsP->init_type) {
125a7e14dcfSSatish Balay     case NLS_INIT_CONSTANT:
126a7e14dcfSSatish Balay       /* Use the initial radius specified */
127a7e14dcfSSatish Balay       break;
128a7e14dcfSSatish Balay 
129a7e14dcfSSatish Balay     case NLS_INIT_INTERPOLATION:
130a7e14dcfSSatish Balay       /* Use the initial radius specified */
131a7e14dcfSSatish Balay       max_radius = 0.0;
132a7e14dcfSSatish Balay 
133a7e14dcfSSatish Balay       for (j = 0; j < j_max; ++j) {
134a7e14dcfSSatish Balay         fmin  = f;
135a7e14dcfSSatish Balay         sigma = 0.0;
136a7e14dcfSSatish Balay 
137a7e14dcfSSatish Balay         if (needH) {
1389566063dSJacob Faibussowitsch           PetscCall(TaoComputeHessian(tao, tao->solution, tao->hessian, tao->hessian_pre));
139a7e14dcfSSatish Balay           needH = 0;
140a7e14dcfSSatish Balay         }
141a7e14dcfSSatish Balay 
142a7e14dcfSSatish Balay         for (i = 0; i < i_max; ++i) {
1439566063dSJacob Faibussowitsch           PetscCall(VecCopy(tao->solution, nlsP->W));
1449566063dSJacob Faibussowitsch           PetscCall(VecAXPY(nlsP->W, -tao->trust / gnorm, tao->gradient));
1459566063dSJacob Faibussowitsch           PetscCall(TaoComputeObjective(tao, nlsP->W, &ftrial));
146a7e14dcfSSatish Balay           if (PetscIsInfOrNanReal(ftrial)) {
147a7e14dcfSSatish Balay             tau = nlsP->gamma1_i;
14887f595a5SBarry Smith           } else {
149a7e14dcfSSatish Balay             if (ftrial < fmin) {
150a7e14dcfSSatish Balay               fmin  = ftrial;
151a7e14dcfSSatish Balay               sigma = -tao->trust / gnorm;
152a7e14dcfSSatish Balay             }
153a7e14dcfSSatish Balay 
1549566063dSJacob Faibussowitsch             PetscCall(MatMult(tao->hessian, tao->gradient, nlsP->D));
1559566063dSJacob Faibussowitsch             PetscCall(VecDot(tao->gradient, nlsP->D, &prered));
156a7e14dcfSSatish Balay 
157a7e14dcfSSatish Balay             prered = tao->trust * (gnorm - 0.5 * tao->trust * prered / (gnorm * gnorm));
158a7e14dcfSSatish Balay             actred = f - ftrial;
15987f595a5SBarry Smith             if ((PetscAbsScalar(actred) <= nlsP->epsilon) && (PetscAbsScalar(prered) <= nlsP->epsilon)) {
160a7e14dcfSSatish Balay               kappa = 1.0;
16187f595a5SBarry Smith             } else {
162a7e14dcfSSatish Balay               kappa = actred / prered;
163a7e14dcfSSatish Balay             }
164a7e14dcfSSatish Balay 
165a7e14dcfSSatish Balay             tau_1   = nlsP->theta_i * gnorm * tao->trust / (nlsP->theta_i * gnorm * tao->trust + (1.0 - nlsP->theta_i) * prered - actred);
166a7e14dcfSSatish Balay             tau_2   = nlsP->theta_i * gnorm * tao->trust / (nlsP->theta_i * gnorm * tao->trust - (1.0 + nlsP->theta_i) * prered + actred);
167a7e14dcfSSatish Balay             tau_min = PetscMin(tau_1, tau_2);
168a7e14dcfSSatish Balay             tau_max = PetscMax(tau_1, tau_2);
169a7e14dcfSSatish Balay 
17018cfbf8eSSatish Balay             if (PetscAbsScalar(kappa - (PetscReal)1.0) <= nlsP->mu1_i) {
171a7e14dcfSSatish Balay               /* Great agreement */
172a7e14dcfSSatish Balay               max_radius = PetscMax(max_radius, tao->trust);
173a7e14dcfSSatish Balay 
174a7e14dcfSSatish Balay               if (tau_max < 1.0) {
175a7e14dcfSSatish Balay                 tau = nlsP->gamma3_i;
17687f595a5SBarry Smith               } else if (tau_max > nlsP->gamma4_i) {
177a7e14dcfSSatish Balay                 tau = nlsP->gamma4_i;
17887f595a5SBarry Smith               } else if (tau_1 >= 1.0 && tau_1 <= nlsP->gamma4_i && tau_2 < 1.0) {
179a7e14dcfSSatish Balay                 tau = tau_1;
18087f595a5SBarry Smith               } else if (tau_2 >= 1.0 && tau_2 <= nlsP->gamma4_i && tau_1 < 1.0) {
181a7e14dcfSSatish Balay                 tau = tau_2;
18287f595a5SBarry Smith               } else {
183a7e14dcfSSatish Balay                 tau = tau_max;
184a7e14dcfSSatish Balay               }
18518cfbf8eSSatish Balay             } else if (PetscAbsScalar(kappa - (PetscReal)1.0) <= nlsP->mu2_i) {
186a7e14dcfSSatish Balay               /* Good agreement */
187a7e14dcfSSatish Balay               max_radius = PetscMax(max_radius, tao->trust);
188a7e14dcfSSatish Balay 
189a7e14dcfSSatish Balay               if (tau_max < nlsP->gamma2_i) {
190a7e14dcfSSatish Balay                 tau = nlsP->gamma2_i;
19187f595a5SBarry Smith               } else if (tau_max > nlsP->gamma3_i) {
192a7e14dcfSSatish Balay                 tau = nlsP->gamma3_i;
19387f595a5SBarry Smith               } else {
194a7e14dcfSSatish Balay                 tau = tau_max;
195a7e14dcfSSatish Balay               }
19687f595a5SBarry Smith             } else {
197a7e14dcfSSatish Balay               /* Not good agreement */
198a7e14dcfSSatish Balay               if (tau_min > 1.0) {
199a7e14dcfSSatish Balay                 tau = nlsP->gamma2_i;
20087f595a5SBarry Smith               } else if (tau_max < nlsP->gamma1_i) {
201a7e14dcfSSatish Balay                 tau = nlsP->gamma1_i;
20287f595a5SBarry Smith               } else if ((tau_min < nlsP->gamma1_i) && (tau_max >= 1.0)) {
203a7e14dcfSSatish Balay                 tau = nlsP->gamma1_i;
20487f595a5SBarry Smith               } else if ((tau_1 >= nlsP->gamma1_i) && (tau_1 < 1.0) && ((tau_2 < nlsP->gamma1_i) || (tau_2 >= 1.0))) {
205a7e14dcfSSatish Balay                 tau = tau_1;
20687f595a5SBarry Smith               } else if ((tau_2 >= nlsP->gamma1_i) && (tau_2 < 1.0) && ((tau_1 < nlsP->gamma1_i) || (tau_2 >= 1.0))) {
207a7e14dcfSSatish Balay                 tau = tau_2;
20887f595a5SBarry Smith               } else {
209a7e14dcfSSatish Balay                 tau = tau_max;
210a7e14dcfSSatish Balay               }
211a7e14dcfSSatish Balay             }
212a7e14dcfSSatish Balay           }
213a7e14dcfSSatish Balay           tao->trust = tau * tao->trust;
214a7e14dcfSSatish Balay         }
215a7e14dcfSSatish Balay 
216a7e14dcfSSatish Balay         if (fmin < f) {
217a7e14dcfSSatish Balay           f = fmin;
2189566063dSJacob Faibussowitsch           PetscCall(VecAXPY(tao->solution, sigma, tao->gradient));
2199566063dSJacob Faibussowitsch           PetscCall(TaoComputeGradient(tao, tao->solution, tao->gradient));
220a7e14dcfSSatish Balay 
2219566063dSJacob Faibussowitsch           PetscCall(TaoGradientNorm(tao, tao->gradient, NORM_2, &gnorm));
2223c859ba3SBarry Smith           PetscCheck(!PetscIsInfOrNanReal(gnorm), PetscObjectComm((PetscObject)tao), PETSC_ERR_USER, "User provided compute gradient generated Inf or NaN");
223a7e14dcfSSatish Balay           needH = 1;
224a7e14dcfSSatish Balay 
2259566063dSJacob Faibussowitsch           PetscCall(TaoLogConvergenceHistory(tao, f, gnorm, 0.0, tao->ksp_its));
2269566063dSJacob Faibussowitsch           PetscCall(TaoMonitor(tao, tao->niter, f, gnorm, 0.0, step));
227dbbe0bcdSBarry Smith           PetscUseTypeMethod(tao, convergencetest, tao->cnvP);
2283ecd9318SAlp Dener           if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0);
229a7e14dcfSSatish Balay         }
230a7e14dcfSSatish Balay       }
231a7e14dcfSSatish Balay       tao->trust = PetscMax(tao->trust, max_radius);
232a7e14dcfSSatish Balay 
233a7e14dcfSSatish Balay       /* Modify the radius if it is too large or small */
234a7e14dcfSSatish Balay       tao->trust = PetscMax(tao->trust, nlsP->min_radius);
235a7e14dcfSSatish Balay       tao->trust = PetscMin(tao->trust, nlsP->max_radius);
236a7e14dcfSSatish Balay       break;
237a7e14dcfSSatish Balay 
238a7e14dcfSSatish Balay     default:
239a7e14dcfSSatish Balay       /* Norm of the first direction will initialize radius */
240a7e14dcfSSatish Balay       tao->trust = 0.0;
241a7e14dcfSSatish Balay       break;
242a7e14dcfSSatish Balay     }
243a7e14dcfSSatish Balay   }
244a7e14dcfSSatish Balay 
245a7e14dcfSSatish Balay   /* Set counter for gradient/reset steps*/
246a7e14dcfSSatish Balay   nlsP->newt = 0;
247a7e14dcfSSatish Balay   nlsP->bfgs = 0;
248a7e14dcfSSatish Balay   nlsP->grad = 0;
249a7e14dcfSSatish Balay 
250a7e14dcfSSatish Balay   /* Have not converged; continue with Newton method */
2513ecd9318SAlp Dener   while (tao->reason == TAO_CONTINUE_ITERATING) {
252e1e80dc8SAlp Dener     /* Call general purpose update function */
253dbbe0bcdSBarry Smith     PetscTryTypeMethod(tao, update, tao->niter, tao->user_update);
2548931d482SJason Sarich     ++tao->niter;
255ae93cb3cSJason Sarich     tao->ksp_its = 0;
256a7e14dcfSSatish Balay 
257a7e14dcfSSatish Balay     /* Compute the Hessian */
2581baa6e33SBarry Smith     if (needH) PetscCall(TaoComputeHessian(tao, tao->solution, tao->hessian, tao->hessian_pre));
259a7e14dcfSSatish Balay 
260a7e14dcfSSatish Balay     /* Shift the Hessian matrix */
261a7e14dcfSSatish Balay     if (pert > 0) {
2629566063dSJacob Faibussowitsch       PetscCall(MatShift(tao->hessian, pert));
26348a46eb9SPierre Jolivet       if (tao->hessian != tao->hessian_pre) PetscCall(MatShift(tao->hessian_pre, pert));
264a7e14dcfSSatish Balay     }
265a7e14dcfSSatish Balay 
2660c51296cSAlp Dener     if (nlsP->bfgs_pre) {
2679566063dSJacob Faibussowitsch       PetscCall(MatLMVMUpdate(nlsP->M, tao->solution, tao->gradient));
268a7e14dcfSSatish Balay       ++bfgsUpdates;
269a7e14dcfSSatish Balay     }
270a7e14dcfSSatish Balay 
271a7e14dcfSSatish Balay     /* Solve the Newton system of equations */
2729566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(tao->ksp, tao->hessian, tao->hessian_pre));
2731daac38eSTodd Munson     if (is_nash || is_stcg || is_gltr) {
2749566063dSJacob Faibussowitsch       PetscCall(KSPCGSetRadius(tao->ksp, nlsP->max_radius));
2759566063dSJacob Faibussowitsch       PetscCall(KSPSolve(tao->ksp, tao->gradient, nlsP->D));
2769566063dSJacob Faibussowitsch       PetscCall(KSPGetIterationNumber(tao->ksp, &kspits));
277a7e14dcfSSatish Balay       tao->ksp_its += kspits;
278ae93cb3cSJason Sarich       tao->ksp_tot_its += kspits;
2799566063dSJacob Faibussowitsch       PetscCall(KSPCGGetNormD(tao->ksp, &norm_d));
280a7e14dcfSSatish Balay 
281a7e14dcfSSatish Balay       if (0.0 == tao->trust) {
282a7e14dcfSSatish Balay         /* Radius was uninitialized; use the norm of the direction */
283a7e14dcfSSatish Balay         if (norm_d > 0.0) {
284a7e14dcfSSatish Balay           tao->trust = norm_d;
285a7e14dcfSSatish Balay 
286a7e14dcfSSatish Balay           /* Modify the radius if it is too large or small */
287a7e14dcfSSatish Balay           tao->trust = PetscMax(tao->trust, nlsP->min_radius);
288a7e14dcfSSatish Balay           tao->trust = PetscMin(tao->trust, nlsP->max_radius);
28987f595a5SBarry Smith         } else {
290a7e14dcfSSatish Balay           /* The direction was bad; set radius to default value and re-solve
291a7e14dcfSSatish Balay              the trust-region subproblem to get a direction */
292a7e14dcfSSatish Balay           tao->trust = tao->trust0;
293a7e14dcfSSatish Balay 
294a7e14dcfSSatish Balay           /* Modify the radius if it is too large or small */
295a7e14dcfSSatish Balay           tao->trust = PetscMax(tao->trust, nlsP->min_radius);
296a7e14dcfSSatish Balay           tao->trust = PetscMin(tao->trust, nlsP->max_radius);
297a7e14dcfSSatish Balay 
2989566063dSJacob Faibussowitsch           PetscCall(KSPCGSetRadius(tao->ksp, nlsP->max_radius));
2999566063dSJacob Faibussowitsch           PetscCall(KSPSolve(tao->ksp, tao->gradient, nlsP->D));
3009566063dSJacob Faibussowitsch           PetscCall(KSPGetIterationNumber(tao->ksp, &kspits));
301a7e14dcfSSatish Balay           tao->ksp_its += kspits;
302ae93cb3cSJason Sarich           tao->ksp_tot_its += kspits;
3039566063dSJacob Faibussowitsch           PetscCall(KSPCGGetNormD(tao->ksp, &norm_d));
304a7e14dcfSSatish Balay 
3053c859ba3SBarry Smith           PetscCheck(norm_d != 0.0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Initial direction zero");
306a7e14dcfSSatish Balay         }
307a7e14dcfSSatish Balay       }
30887f595a5SBarry Smith     } else {
3099566063dSJacob Faibussowitsch       PetscCall(KSPSolve(tao->ksp, tao->gradient, nlsP->D));
3109566063dSJacob Faibussowitsch       PetscCall(KSPGetIterationNumber(tao->ksp, &kspits));
311a7e14dcfSSatish Balay       tao->ksp_its += kspits;
312ae93cb3cSJason Sarich       tao->ksp_tot_its += kspits;
313a7e14dcfSSatish Balay     }
3149566063dSJacob Faibussowitsch     PetscCall(VecScale(nlsP->D, -1.0));
3159566063dSJacob Faibussowitsch     PetscCall(KSPGetConvergedReason(tao->ksp, &ksp_reason));
3160c51296cSAlp Dener     if ((KSP_DIVERGED_INDEFINITE_PC == ksp_reason) && (nlsP->bfgs_pre)) {
317a7e14dcfSSatish Balay       /* Preconditioner is numerically indefinite; reset the
318a7e14dcfSSatish Balay          approximate if using BFGS preconditioning. */
3199566063dSJacob Faibussowitsch       PetscCall(MatLMVMReset(nlsP->M, PETSC_FALSE));
3209566063dSJacob Faibussowitsch       PetscCall(MatLMVMUpdate(nlsP->M, tao->solution, tao->gradient));
321a7e14dcfSSatish Balay       bfgsUpdates = 1;
322a7e14dcfSSatish Balay     }
323a7e14dcfSSatish Balay 
324a7e14dcfSSatish Balay     if (KSP_CONVERGED_ATOL == ksp_reason) {
325a7e14dcfSSatish Balay       ++nlsP->ksp_atol;
32687f595a5SBarry Smith     } else if (KSP_CONVERGED_RTOL == ksp_reason) {
327a7e14dcfSSatish Balay       ++nlsP->ksp_rtol;
32887f595a5SBarry Smith     } else if (KSP_CONVERGED_CG_CONSTRAINED == ksp_reason) {
329a7e14dcfSSatish Balay       ++nlsP->ksp_ctol;
33087f595a5SBarry Smith     } else if (KSP_CONVERGED_CG_NEG_CURVE == ksp_reason) {
331a7e14dcfSSatish Balay       ++nlsP->ksp_negc;
33287f595a5SBarry Smith     } else if (KSP_DIVERGED_DTOL == ksp_reason) {
333a7e14dcfSSatish Balay       ++nlsP->ksp_dtol;
33487f595a5SBarry Smith     } else if (KSP_DIVERGED_ITS == ksp_reason) {
335a7e14dcfSSatish Balay       ++nlsP->ksp_iter;
33687f595a5SBarry Smith     } else {
337a7e14dcfSSatish Balay       ++nlsP->ksp_othr;
338a7e14dcfSSatish Balay     }
339a7e14dcfSSatish Balay 
340a7e14dcfSSatish Balay     /* Check for success (descent direction) */
3419566063dSJacob Faibussowitsch     PetscCall(VecDot(nlsP->D, tao->gradient, &gdx));
342a7e14dcfSSatish Balay     if ((gdx >= 0.0) || PetscIsInfOrNanReal(gdx)) {
343a7e14dcfSSatish Balay       /* Newton step is not descent or direction produced Inf or NaN
344a7e14dcfSSatish Balay          Update the perturbation for next time */
345a7e14dcfSSatish Balay       if (pert <= 0.0) {
346a7e14dcfSSatish Balay         /* Initialize the perturbation */
347a7e14dcfSSatish Balay         pert = PetscMin(nlsP->imax, PetscMax(nlsP->imin, nlsP->imfac * gnorm));
3481daac38eSTodd Munson         if (is_gltr) {
3499566063dSJacob Faibussowitsch           PetscCall(KSPGLTRGetMinEig(tao->ksp, &e_min));
350a7e14dcfSSatish Balay           pert = PetscMax(pert, -e_min);
351a7e14dcfSSatish Balay         }
35287f595a5SBarry Smith       } else {
353a7e14dcfSSatish Balay         /* Increase the perturbation */
354a7e14dcfSSatish Balay         pert = PetscMin(nlsP->pmax, PetscMax(nlsP->pgfac * pert, nlsP->pmgfac * gnorm));
355a7e14dcfSSatish Balay       }
356a7e14dcfSSatish Balay 
3570c51296cSAlp Dener       if (!nlsP->bfgs_pre) {
358a7e14dcfSSatish Balay         /* We don't have the bfgs matrix around and updated
359a7e14dcfSSatish Balay            Must use gradient direction in this case */
3609566063dSJacob Faibussowitsch         PetscCall(VecCopy(tao->gradient, nlsP->D));
3619566063dSJacob Faibussowitsch         PetscCall(VecScale(nlsP->D, -1.0));
362a7e14dcfSSatish Balay         ++nlsP->grad;
363a7e14dcfSSatish Balay         stepType = NLS_GRADIENT;
36487f595a5SBarry Smith       } else {
365a7e14dcfSSatish Balay         /* Attempt to use the BFGS direction */
3669566063dSJacob Faibussowitsch         PetscCall(MatSolve(nlsP->M, tao->gradient, nlsP->D));
3679566063dSJacob Faibussowitsch         PetscCall(VecScale(nlsP->D, -1.0));
368a7e14dcfSSatish Balay 
369a7e14dcfSSatish Balay         /* Check for success (descent direction) */
3709566063dSJacob Faibussowitsch         PetscCall(VecDot(tao->gradient, nlsP->D, &gdx));
371a7e14dcfSSatish Balay         if ((gdx >= 0) || PetscIsInfOrNanReal(gdx)) {
372a7e14dcfSSatish Balay           /* BFGS direction is not descent or direction produced not a number
373a7e14dcfSSatish Balay              We can assert bfgsUpdates > 1 in this case because
374a7e14dcfSSatish Balay              the first solve produces the scaled gradient direction,
375a7e14dcfSSatish Balay              which is guaranteed to be descent */
376a7e14dcfSSatish Balay 
377a7e14dcfSSatish Balay           /* Use steepest descent direction (scaled) */
3789566063dSJacob Faibussowitsch           PetscCall(MatLMVMReset(nlsP->M, PETSC_FALSE));
3799566063dSJacob Faibussowitsch           PetscCall(MatLMVMUpdate(nlsP->M, tao->solution, tao->gradient));
3809566063dSJacob Faibussowitsch           PetscCall(MatSolve(nlsP->M, tao->gradient, nlsP->D));
3819566063dSJacob Faibussowitsch           PetscCall(VecScale(nlsP->D, -1.0));
382a7e14dcfSSatish Balay 
383a7e14dcfSSatish Balay           bfgsUpdates = 1;
3840c51296cSAlp Dener           ++nlsP->grad;
3850c51296cSAlp Dener           stepType = NLS_GRADIENT;
38687f595a5SBarry Smith         } else {
3879566063dSJacob Faibussowitsch           PetscCall(MatLMVMGetUpdateCount(nlsP->M, &bfgsUpdates));
388a7e14dcfSSatish Balay           if (1 == bfgsUpdates) {
389a7e14dcfSSatish Balay             /* The first BFGS direction is always the scaled gradient */
3900c51296cSAlp Dener             ++nlsP->grad;
3910c51296cSAlp Dener             stepType = NLS_GRADIENT;
39287f595a5SBarry Smith           } else {
393a7e14dcfSSatish Balay             ++nlsP->bfgs;
394a7e14dcfSSatish Balay             stepType = NLS_BFGS;
395a7e14dcfSSatish Balay           }
396a7e14dcfSSatish Balay         }
397a7e14dcfSSatish Balay       }
39887f595a5SBarry Smith     } else {
399a7e14dcfSSatish Balay       /* Computed Newton step is descent */
400a7e14dcfSSatish Balay       switch (ksp_reason) {
401a7e14dcfSSatish Balay       case KSP_DIVERGED_NANORINF:
402a7e14dcfSSatish Balay       case KSP_DIVERGED_BREAKDOWN:
403a7e14dcfSSatish Balay       case KSP_DIVERGED_INDEFINITE_MAT:
404a7e14dcfSSatish Balay       case KSP_DIVERGED_INDEFINITE_PC:
405a7e14dcfSSatish Balay       case KSP_CONVERGED_CG_NEG_CURVE:
406a7e14dcfSSatish Balay         /* Matrix or preconditioner is indefinite; increase perturbation */
407a7e14dcfSSatish Balay         if (pert <= 0.0) {
408a7e14dcfSSatish Balay           /* Initialize the perturbation */
409a7e14dcfSSatish Balay           pert = PetscMin(nlsP->imax, PetscMax(nlsP->imin, nlsP->imfac * gnorm));
4101daac38eSTodd Munson           if (is_gltr) {
4119566063dSJacob Faibussowitsch             PetscCall(KSPGLTRGetMinEig(tao->ksp, &e_min));
412a7e14dcfSSatish Balay             pert = PetscMax(pert, -e_min);
413a7e14dcfSSatish Balay           }
41487f595a5SBarry Smith         } else {
415a7e14dcfSSatish Balay           /* Increase the perturbation */
416a7e14dcfSSatish Balay           pert = PetscMin(nlsP->pmax, PetscMax(nlsP->pgfac * pert, nlsP->pmgfac * gnorm));
417a7e14dcfSSatish Balay         }
418a7e14dcfSSatish Balay         break;
419a7e14dcfSSatish Balay 
420a7e14dcfSSatish Balay       default:
421a7e14dcfSSatish Balay         /* Newton step computation is good; decrease perturbation */
422a7e14dcfSSatish Balay         pert = PetscMin(nlsP->psfac * pert, nlsP->pmsfac * gnorm);
423ad540459SPierre Jolivet         if (pert < nlsP->pmin) pert = 0.0;
424a7e14dcfSSatish Balay         break;
425a7e14dcfSSatish Balay       }
426a7e14dcfSSatish Balay 
427a7e14dcfSSatish Balay       ++nlsP->newt;
428a7e14dcfSSatish Balay       stepType = NLS_NEWTON;
429a7e14dcfSSatish Balay     }
430a7e14dcfSSatish Balay 
431a7e14dcfSSatish Balay     /* Perform the linesearch */
432a7e14dcfSSatish Balay     fold = f;
4339566063dSJacob Faibussowitsch     PetscCall(VecCopy(tao->solution, nlsP->Xold));
4349566063dSJacob Faibussowitsch     PetscCall(VecCopy(tao->gradient, nlsP->Gold));
435a7e14dcfSSatish Balay 
4369566063dSJacob Faibussowitsch     PetscCall(TaoLineSearchApply(tao->linesearch, tao->solution, &f, tao->gradient, nlsP->D, &step, &ls_reason));
4379566063dSJacob Faibussowitsch     PetscCall(TaoAddLineSearchCounts(tao));
438a7e14dcfSSatish Balay 
43987f595a5SBarry Smith     while (ls_reason != TAOLINESEARCH_SUCCESS && ls_reason != TAOLINESEARCH_SUCCESS_USER && stepType != NLS_GRADIENT) { /* Linesearch failed */
440a7e14dcfSSatish Balay       f = fold;
4419566063dSJacob Faibussowitsch       PetscCall(VecCopy(nlsP->Xold, tao->solution));
4429566063dSJacob Faibussowitsch       PetscCall(VecCopy(nlsP->Gold, tao->gradient));
443a7e14dcfSSatish Balay 
444a7e14dcfSSatish Balay       switch (stepType) {
445a7e14dcfSSatish Balay       case NLS_NEWTON:
446a7e14dcfSSatish Balay         /* Failed to obtain acceptable iterate with Newton 1step
447a7e14dcfSSatish Balay            Update the perturbation for next time */
448a7e14dcfSSatish Balay         if (pert <= 0.0) {
449a7e14dcfSSatish Balay           /* Initialize the perturbation */
450a7e14dcfSSatish Balay           pert = PetscMin(nlsP->imax, PetscMax(nlsP->imin, nlsP->imfac * gnorm));
4511daac38eSTodd Munson           if (is_gltr) {
4529566063dSJacob Faibussowitsch             PetscCall(KSPGLTRGetMinEig(tao->ksp, &e_min));
453a7e14dcfSSatish Balay             pert = PetscMax(pert, -e_min);
454a7e14dcfSSatish Balay           }
45587f595a5SBarry Smith         } else {
456a7e14dcfSSatish Balay           /* Increase the perturbation */
457a7e14dcfSSatish Balay           pert = PetscMin(nlsP->pmax, PetscMax(nlsP->pgfac * pert, nlsP->pmgfac * gnorm));
458a7e14dcfSSatish Balay         }
459a7e14dcfSSatish Balay 
4600c51296cSAlp Dener         if (!nlsP->bfgs_pre) {
461a7e14dcfSSatish Balay           /* We don't have the bfgs matrix around and being updated
462a7e14dcfSSatish Balay              Must use gradient direction in this case */
4639566063dSJacob Faibussowitsch           PetscCall(VecCopy(tao->gradient, nlsP->D));
464a7e14dcfSSatish Balay           ++nlsP->grad;
465a7e14dcfSSatish Balay           stepType = NLS_GRADIENT;
46687f595a5SBarry Smith         } else {
467a7e14dcfSSatish Balay           /* Attempt to use the BFGS direction */
4689566063dSJacob Faibussowitsch           PetscCall(MatSolve(nlsP->M, tao->gradient, nlsP->D));
469a7e14dcfSSatish Balay           /* Check for success (descent direction) */
4709566063dSJacob Faibussowitsch           PetscCall(VecDot(tao->solution, nlsP->D, &gdx));
471a7e14dcfSSatish Balay           if ((gdx <= 0) || PetscIsInfOrNanReal(gdx)) {
472a7e14dcfSSatish Balay             /* BFGS direction is not descent or direction produced not a number
473a7e14dcfSSatish Balay                We can assert bfgsUpdates > 1 in this case
474a7e14dcfSSatish Balay                Use steepest descent direction (scaled) */
4759566063dSJacob Faibussowitsch             PetscCall(MatLMVMReset(nlsP->M, PETSC_FALSE));
4769566063dSJacob Faibussowitsch             PetscCall(MatLMVMUpdate(nlsP->M, tao->solution, tao->gradient));
4779566063dSJacob Faibussowitsch             PetscCall(MatSolve(nlsP->M, tao->gradient, nlsP->D));
478a7e14dcfSSatish Balay 
479a7e14dcfSSatish Balay             bfgsUpdates = 1;
4800c51296cSAlp Dener             ++nlsP->grad;
4810c51296cSAlp Dener             stepType = NLS_GRADIENT;
48287f595a5SBarry Smith           } else {
483a7e14dcfSSatish Balay             if (1 == bfgsUpdates) {
484a7e14dcfSSatish Balay               /* The first BFGS direction is always the scaled gradient */
4850c51296cSAlp Dener               ++nlsP->grad;
4860c51296cSAlp Dener               stepType = NLS_GRADIENT;
48787f595a5SBarry Smith             } else {
488a7e14dcfSSatish Balay               ++nlsP->bfgs;
489a7e14dcfSSatish Balay               stepType = NLS_BFGS;
490a7e14dcfSSatish Balay             }
491a7e14dcfSSatish Balay           }
492a7e14dcfSSatish Balay         }
493a7e14dcfSSatish Balay         break;
494a7e14dcfSSatish Balay 
495a7e14dcfSSatish Balay       case NLS_BFGS:
496a7e14dcfSSatish Balay         /* Can only enter if pc_type == NLS_PC_BFGS
497a7e14dcfSSatish Balay            Failed to obtain acceptable iterate with BFGS step
498a7e14dcfSSatish Balay            Attempt to use the scaled gradient direction */
4999566063dSJacob Faibussowitsch         PetscCall(MatLMVMReset(nlsP->M, PETSC_FALSE));
5009566063dSJacob Faibussowitsch         PetscCall(MatLMVMUpdate(nlsP->M, tao->solution, tao->gradient));
5019566063dSJacob Faibussowitsch         PetscCall(MatSolve(nlsP->M, tao->gradient, nlsP->D));
502a7e14dcfSSatish Balay 
503a7e14dcfSSatish Balay         bfgsUpdates = 1;
504a7e14dcfSSatish Balay         ++nlsP->grad;
505a7e14dcfSSatish Balay         stepType = NLS_GRADIENT;
506a7e14dcfSSatish Balay         break;
507a7e14dcfSSatish Balay       }
5089566063dSJacob Faibussowitsch       PetscCall(VecScale(nlsP->D, -1.0));
509a7e14dcfSSatish Balay 
5109566063dSJacob Faibussowitsch       PetscCall(TaoLineSearchApply(tao->linesearch, tao->solution, &f, tao->gradient, nlsP->D, &step, &ls_reason));
5119566063dSJacob Faibussowitsch       PetscCall(TaoLineSearchGetFullStepObjective(tao->linesearch, &f_full));
5129566063dSJacob Faibussowitsch       PetscCall(TaoAddLineSearchCounts(tao));
513a7e14dcfSSatish Balay     }
514a7e14dcfSSatish Balay 
51587f595a5SBarry Smith     if (ls_reason != TAOLINESEARCH_SUCCESS && ls_reason != TAOLINESEARCH_SUCCESS_USER) {
516a7e14dcfSSatish Balay       /* Failed to find an improving point */
517a7e14dcfSSatish Balay       f = fold;
5189566063dSJacob Faibussowitsch       PetscCall(VecCopy(nlsP->Xold, tao->solution));
5199566063dSJacob Faibussowitsch       PetscCall(VecCopy(nlsP->Gold, tao->gradient));
520a7e14dcfSSatish Balay       step        = 0.0;
521a7e14dcfSSatish Balay       tao->reason = TAO_DIVERGED_LS_FAILURE;
522a7e14dcfSSatish Balay       break;
523a7e14dcfSSatish Balay     }
524a7e14dcfSSatish Balay 
525a7e14dcfSSatish Balay     /* Update trust region radius */
5261daac38eSTodd Munson     if (is_nash || is_stcg || is_gltr) {
527a7e14dcfSSatish Balay       switch (nlsP->update_type) {
528a7e14dcfSSatish Balay       case NLS_UPDATE_STEP:
529a7e14dcfSSatish Balay         if (stepType == NLS_NEWTON) {
530a7e14dcfSSatish Balay           if (step < nlsP->nu1) {
531a7e14dcfSSatish Balay             /* Very bad step taken; reduce radius */
532a7e14dcfSSatish Balay             tao->trust = nlsP->omega1 * PetscMin(norm_d, tao->trust);
53387f595a5SBarry Smith           } else if (step < nlsP->nu2) {
534a7e14dcfSSatish Balay             /* Reasonably bad step taken; reduce radius */
535a7e14dcfSSatish Balay             tao->trust = nlsP->omega2 * PetscMin(norm_d, tao->trust);
53687f595a5SBarry Smith           } else if (step < nlsP->nu3) {
537a7e14dcfSSatish Balay             /*  Reasonable step was taken; leave radius alone */
538a7e14dcfSSatish Balay             if (nlsP->omega3 < 1.0) {
539a7e14dcfSSatish Balay               tao->trust = nlsP->omega3 * PetscMin(norm_d, tao->trust);
54087f595a5SBarry Smith             } else if (nlsP->omega3 > 1.0) {
541a7e14dcfSSatish Balay               tao->trust = PetscMax(nlsP->omega3 * norm_d, tao->trust);
542a7e14dcfSSatish Balay             }
54387f595a5SBarry Smith           } else if (step < nlsP->nu4) {
544a7e14dcfSSatish Balay             /*  Full step taken; increase the radius */
545a7e14dcfSSatish Balay             tao->trust = PetscMax(nlsP->omega4 * norm_d, tao->trust);
54687f595a5SBarry Smith           } else {
547a7e14dcfSSatish Balay             /*  More than full step taken; increase the radius */
548a7e14dcfSSatish Balay             tao->trust = PetscMax(nlsP->omega5 * norm_d, tao->trust);
549a7e14dcfSSatish Balay           }
55087f595a5SBarry Smith         } else {
551a7e14dcfSSatish Balay           /*  Newton step was not good; reduce the radius */
552a7e14dcfSSatish Balay           tao->trust = nlsP->omega1 * PetscMin(norm_d, tao->trust);
553a7e14dcfSSatish Balay         }
554a7e14dcfSSatish Balay         break;
555a7e14dcfSSatish Balay 
556a7e14dcfSSatish Balay       case NLS_UPDATE_REDUCTION:
557a7e14dcfSSatish Balay         if (stepType == NLS_NEWTON) {
558a7e14dcfSSatish Balay           /*  Get predicted reduction */
559a7e14dcfSSatish Balay 
5609566063dSJacob Faibussowitsch           PetscCall(KSPCGGetObjFcn(tao->ksp, &prered));
561a7e14dcfSSatish Balay           if (prered >= 0.0) {
562a7e14dcfSSatish Balay             /*  The predicted reduction has the wrong sign.  This cannot */
563a7e14dcfSSatish Balay             /*  happen in infinite precision arithmetic.  Step should */
564a7e14dcfSSatish Balay             /*  be rejected! */
565a7e14dcfSSatish Balay             tao->trust = nlsP->alpha1 * PetscMin(tao->trust, norm_d);
56687f595a5SBarry Smith           } else {
567a7e14dcfSSatish Balay             if (PetscIsInfOrNanReal(f_full)) {
568a7e14dcfSSatish Balay               tao->trust = nlsP->alpha1 * PetscMin(tao->trust, norm_d);
56987f595a5SBarry Smith             } else {
570a7e14dcfSSatish Balay               /*  Compute and actual reduction */
571a7e14dcfSSatish Balay               actred = fold - f_full;
572a7e14dcfSSatish Balay               prered = -prered;
5739371c9d4SSatish Balay               if ((PetscAbsScalar(actred) <= nlsP->epsilon) && (PetscAbsScalar(prered) <= nlsP->epsilon)) {
574a7e14dcfSSatish Balay                 kappa = 1.0;
57587f595a5SBarry Smith               } else {
576a7e14dcfSSatish Balay                 kappa = actred / prered;
577a7e14dcfSSatish Balay               }
578a7e14dcfSSatish Balay 
579a7e14dcfSSatish Balay               /*  Accept of reject the step and update radius */
580a7e14dcfSSatish Balay               if (kappa < nlsP->eta1) {
581a7e14dcfSSatish Balay                 /*  Very bad step */
582a7e14dcfSSatish Balay                 tao->trust = nlsP->alpha1 * PetscMin(tao->trust, norm_d);
58387f595a5SBarry Smith               } else if (kappa < nlsP->eta2) {
584a7e14dcfSSatish Balay                 /*  Marginal bad step */
585a7e14dcfSSatish Balay                 tao->trust = nlsP->alpha2 * PetscMin(tao->trust, norm_d);
58687f595a5SBarry Smith               } else if (kappa < nlsP->eta3) {
587a7e14dcfSSatish Balay                 /*  Reasonable step */
588a7e14dcfSSatish Balay                 if (nlsP->alpha3 < 1.0) {
589a7e14dcfSSatish Balay                   tao->trust = nlsP->alpha3 * PetscMin(norm_d, tao->trust);
59087f595a5SBarry Smith                 } else if (nlsP->alpha3 > 1.0) {
591a7e14dcfSSatish Balay                   tao->trust = PetscMax(nlsP->alpha3 * norm_d, tao->trust);
592a7e14dcfSSatish Balay                 }
59387f595a5SBarry Smith               } else if (kappa < nlsP->eta4) {
594a7e14dcfSSatish Balay                 /*  Good step */
595a7e14dcfSSatish Balay                 tao->trust = PetscMax(nlsP->alpha4 * norm_d, tao->trust);
59687f595a5SBarry Smith               } else {
597a7e14dcfSSatish Balay                 /*  Very good step */
598a7e14dcfSSatish Balay                 tao->trust = PetscMax(nlsP->alpha5 * norm_d, tao->trust);
599a7e14dcfSSatish Balay               }
600a7e14dcfSSatish Balay             }
601a7e14dcfSSatish Balay           }
60287f595a5SBarry Smith         } else {
603a7e14dcfSSatish Balay           /*  Newton step was not good; reduce the radius */
604a7e14dcfSSatish Balay           tao->trust = nlsP->alpha1 * PetscMin(norm_d, tao->trust);
605a7e14dcfSSatish Balay         }
606a7e14dcfSSatish Balay         break;
607a7e14dcfSSatish Balay 
608a7e14dcfSSatish Balay       default:
609a7e14dcfSSatish Balay         if (stepType == NLS_NEWTON) {
6109566063dSJacob Faibussowitsch           PetscCall(KSPCGGetObjFcn(tao->ksp, &prered));
611a7e14dcfSSatish Balay           if (prered >= 0.0) {
612a7e14dcfSSatish Balay             /*  The predicted reduction has the wrong sign.  This cannot */
613a7e14dcfSSatish Balay             /*  happen in infinite precision arithmetic.  Step should */
614a7e14dcfSSatish Balay             /*  be rejected! */
615a7e14dcfSSatish Balay             tao->trust = nlsP->gamma1 * PetscMin(tao->trust, norm_d);
61687f595a5SBarry Smith           } else {
617a7e14dcfSSatish Balay             if (PetscIsInfOrNanReal(f_full)) {
618a7e14dcfSSatish Balay               tao->trust = nlsP->gamma1 * PetscMin(tao->trust, norm_d);
61987f595a5SBarry Smith             } else {
620a7e14dcfSSatish Balay               actred = fold - f_full;
621a7e14dcfSSatish Balay               prered = -prered;
62287f595a5SBarry Smith               if ((PetscAbsScalar(actred) <= nlsP->epsilon) && (PetscAbsScalar(prered) <= nlsP->epsilon)) {
623a7e14dcfSSatish Balay                 kappa = 1.0;
62487f595a5SBarry Smith               } else {
625a7e14dcfSSatish Balay                 kappa = actred / prered;
626a7e14dcfSSatish Balay               }
627a7e14dcfSSatish Balay 
628a7e14dcfSSatish Balay               tau_1   = nlsP->theta * gdx / (nlsP->theta * gdx - (1.0 - nlsP->theta) * prered + actred);
629a7e14dcfSSatish Balay               tau_2   = nlsP->theta * gdx / (nlsP->theta * gdx + (1.0 + nlsP->theta) * prered - actred);
630a7e14dcfSSatish Balay               tau_min = PetscMin(tau_1, tau_2);
631a7e14dcfSSatish Balay               tau_max = PetscMax(tau_1, tau_2);
632a7e14dcfSSatish Balay 
633a7e14dcfSSatish Balay               if (kappa >= 1.0 - nlsP->mu1) {
634a7e14dcfSSatish Balay                 /*  Great agreement */
635a7e14dcfSSatish Balay                 if (tau_max < 1.0) {
636a7e14dcfSSatish Balay                   tao->trust = PetscMax(tao->trust, nlsP->gamma3 * norm_d);
63787f595a5SBarry Smith                 } else if (tau_max > nlsP->gamma4) {
638a7e14dcfSSatish Balay                   tao->trust = PetscMax(tao->trust, nlsP->gamma4 * norm_d);
63987f595a5SBarry Smith                 } else {
640a7e14dcfSSatish Balay                   tao->trust = PetscMax(tao->trust, tau_max * norm_d);
641a7e14dcfSSatish Balay                 }
64287f595a5SBarry Smith               } else if (kappa >= 1.0 - nlsP->mu2) {
643a7e14dcfSSatish Balay                 /*  Good agreement */
644a7e14dcfSSatish Balay 
645a7e14dcfSSatish Balay                 if (tau_max < nlsP->gamma2) {
646a7e14dcfSSatish Balay                   tao->trust = nlsP->gamma2 * PetscMin(tao->trust, norm_d);
64787f595a5SBarry Smith                 } else if (tau_max > nlsP->gamma3) {
648a7e14dcfSSatish Balay                   tao->trust = PetscMax(tao->trust, nlsP->gamma3 * norm_d);
64987f595a5SBarry Smith                 } else if (tau_max < 1.0) {
650a7e14dcfSSatish Balay                   tao->trust = tau_max * PetscMin(tao->trust, norm_d);
65187f595a5SBarry Smith                 } else {
652a7e14dcfSSatish Balay                   tao->trust = PetscMax(tao->trust, tau_max * norm_d);
653a7e14dcfSSatish Balay                 }
65487f595a5SBarry Smith               } else {
655a7e14dcfSSatish Balay                 /*  Not good agreement */
656a7e14dcfSSatish Balay                 if (tau_min > 1.0) {
657a7e14dcfSSatish Balay                   tao->trust = nlsP->gamma2 * PetscMin(tao->trust, norm_d);
65887f595a5SBarry Smith                 } else if (tau_max < nlsP->gamma1) {
659a7e14dcfSSatish Balay                   tao->trust = nlsP->gamma1 * PetscMin(tao->trust, norm_d);
66087f595a5SBarry Smith                 } else if ((tau_min < nlsP->gamma1) && (tau_max >= 1.0)) {
661a7e14dcfSSatish Balay                   tao->trust = nlsP->gamma1 * PetscMin(tao->trust, norm_d);
66287f595a5SBarry Smith                 } else if ((tau_1 >= nlsP->gamma1) && (tau_1 < 1.0) && ((tau_2 < nlsP->gamma1) || (tau_2 >= 1.0))) {
663a7e14dcfSSatish Balay                   tao->trust = tau_1 * PetscMin(tao->trust, norm_d);
66487f595a5SBarry Smith                 } else if ((tau_2 >= nlsP->gamma1) && (tau_2 < 1.0) && ((tau_1 < nlsP->gamma1) || (tau_2 >= 1.0))) {
665a7e14dcfSSatish Balay                   tao->trust = tau_2 * PetscMin(tao->trust, norm_d);
66687f595a5SBarry Smith                 } else {
667a7e14dcfSSatish Balay                   tao->trust = tau_max * PetscMin(tao->trust, norm_d);
668a7e14dcfSSatish Balay                 }
669a7e14dcfSSatish Balay               }
670a7e14dcfSSatish Balay             }
671a7e14dcfSSatish Balay           }
67287f595a5SBarry Smith         } else {
673a7e14dcfSSatish Balay           /*  Newton step was not good; reduce the radius */
674a7e14dcfSSatish Balay           tao->trust = nlsP->gamma1 * PetscMin(norm_d, tao->trust);
675a7e14dcfSSatish Balay         }
676a7e14dcfSSatish Balay         break;
677a7e14dcfSSatish Balay       }
678a7e14dcfSSatish Balay 
679a7e14dcfSSatish Balay       /*  The radius may have been increased; modify if it is too large */
680a7e14dcfSSatish Balay       tao->trust = PetscMin(tao->trust, nlsP->max_radius);
681a7e14dcfSSatish Balay     }
682a7e14dcfSSatish Balay 
683a7e14dcfSSatish Balay     /*  Check for termination */
6849566063dSJacob Faibussowitsch     PetscCall(TaoGradientNorm(tao, tao->gradient, NORM_2, &gnorm));
6853c859ba3SBarry Smith     PetscCheck(!PetscIsInfOrNanReal(f) && !PetscIsInfOrNanReal(gnorm), PetscObjectComm((PetscObject)tao), PETSC_ERR_USER, "User provided compute function generated Not-a-Number");
686a7e14dcfSSatish Balay     needH = 1;
6879566063dSJacob Faibussowitsch     PetscCall(TaoLogConvergenceHistory(tao, f, gnorm, 0.0, tao->ksp_its));
6889566063dSJacob Faibussowitsch     PetscCall(TaoMonitor(tao, tao->niter, f, gnorm, 0.0, step));
689dbbe0bcdSBarry Smith     PetscUseTypeMethod(tao, convergencetest, tao->cnvP);
690a7e14dcfSSatish Balay   }
691a7e14dcfSSatish Balay   PetscFunctionReturn(0);
692a7e14dcfSSatish Balay }
693a7e14dcfSSatish Balay 
694a7e14dcfSSatish Balay /* ---------------------------------------------------------- */
695*d71ae5a4SJacob Faibussowitsch static PetscErrorCode TaoSetUp_NLS(Tao tao)
696*d71ae5a4SJacob Faibussowitsch {
697a7e14dcfSSatish Balay   TAO_NLS *nlsP = (TAO_NLS *)tao->data;
698a7e14dcfSSatish Balay 
699a7e14dcfSSatish Balay   PetscFunctionBegin;
7009566063dSJacob Faibussowitsch   if (!tao->gradient) PetscCall(VecDuplicate(tao->solution, &tao->gradient));
7019566063dSJacob Faibussowitsch   if (!tao->stepdirection) PetscCall(VecDuplicate(tao->solution, &tao->stepdirection));
7029566063dSJacob Faibussowitsch   if (!nlsP->W) PetscCall(VecDuplicate(tao->solution, &nlsP->W));
7039566063dSJacob Faibussowitsch   if (!nlsP->D) PetscCall(VecDuplicate(tao->solution, &nlsP->D));
7049566063dSJacob Faibussowitsch   if (!nlsP->Xold) PetscCall(VecDuplicate(tao->solution, &nlsP->Xold));
7059566063dSJacob Faibussowitsch   if (!nlsP->Gold) PetscCall(VecDuplicate(tao->solution, &nlsP->Gold));
70683c8fe1dSLisandro Dalcin   nlsP->M        = NULL;
70783c8fe1dSLisandro Dalcin   nlsP->bfgs_pre = NULL;
708a7e14dcfSSatish Balay   PetscFunctionReturn(0);
709a7e14dcfSSatish Balay }
710a7e14dcfSSatish Balay 
711a7e14dcfSSatish Balay /*------------------------------------------------------------*/
712*d71ae5a4SJacob Faibussowitsch static PetscErrorCode TaoDestroy_NLS(Tao tao)
713*d71ae5a4SJacob Faibussowitsch {
714a7e14dcfSSatish Balay   TAO_NLS *nlsP = (TAO_NLS *)tao->data;
715a7e14dcfSSatish Balay 
716a7e14dcfSSatish Balay   PetscFunctionBegin;
717a7e14dcfSSatish Balay   if (tao->setupcalled) {
7189566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&nlsP->D));
7199566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&nlsP->W));
7209566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&nlsP->Xold));
7219566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&nlsP->Gold));
722a7e14dcfSSatish Balay   }
723a958fbfcSStefano Zampini   PetscCall(KSPDestroy(&tao->ksp));
7249566063dSJacob Faibussowitsch   PetscCall(PetscFree(tao->data));
725a7e14dcfSSatish Balay   PetscFunctionReturn(0);
726a7e14dcfSSatish Balay }
727a7e14dcfSSatish Balay 
728a7e14dcfSSatish Balay /*------------------------------------------------------------*/
729*d71ae5a4SJacob Faibussowitsch static PetscErrorCode TaoSetFromOptions_NLS(Tao tao, PetscOptionItems *PetscOptionsObject)
730*d71ae5a4SJacob Faibussowitsch {
731a7e14dcfSSatish Balay   TAO_NLS *nlsP = (TAO_NLS *)tao->data;
732a7e14dcfSSatish Balay 
733a7e14dcfSSatish Balay   PetscFunctionBegin;
734d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "Newton line search method for unconstrained optimization");
7359566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-tao_nls_init_type", "radius initialization type", "", NLS_INIT, NLS_INIT_TYPES, NLS_INIT[nlsP->init_type], &nlsP->init_type, NULL));
7369566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-tao_nls_update_type", "radius update type", "", NLS_UPDATE, NLS_UPDATE_TYPES, NLS_UPDATE[nlsP->update_type], &nlsP->update_type, NULL));
7379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_sval", "perturbation starting value", "", nlsP->sval, &nlsP->sval, NULL));
7389566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_imin", "minimum initial perturbation", "", nlsP->imin, &nlsP->imin, NULL));
7399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_imax", "maximum initial perturbation", "", nlsP->imax, &nlsP->imax, NULL));
7409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_imfac", "initial merit factor", "", nlsP->imfac, &nlsP->imfac, NULL));
7419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_pmin", "minimum perturbation", "", nlsP->pmin, &nlsP->pmin, NULL));
7429566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_pmax", "maximum perturbation", "", nlsP->pmax, &nlsP->pmax, NULL));
7439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_pgfac", "growth factor", "", nlsP->pgfac, &nlsP->pgfac, NULL));
7449566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_psfac", "shrink factor", "", nlsP->psfac, &nlsP->psfac, NULL));
7459566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_pmgfac", "merit growth factor", "", nlsP->pmgfac, &nlsP->pmgfac, NULL));
7469566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_pmsfac", "merit shrink factor", "", nlsP->pmsfac, &nlsP->pmsfac, NULL));
7479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_eta1", "poor steplength; reduce radius", "", nlsP->eta1, &nlsP->eta1, NULL));
7489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_eta2", "reasonable steplength; leave radius alone", "", nlsP->eta2, &nlsP->eta2, NULL));
7499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_eta3", "good steplength; increase radius", "", nlsP->eta3, &nlsP->eta3, NULL));
7509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_eta4", "excellent steplength; greatly increase radius", "", nlsP->eta4, &nlsP->eta4, NULL));
7519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_alpha1", "", "", nlsP->alpha1, &nlsP->alpha1, NULL));
7529566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_alpha2", "", "", nlsP->alpha2, &nlsP->alpha2, NULL));
7539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_alpha3", "", "", nlsP->alpha3, &nlsP->alpha3, NULL));
7549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_alpha4", "", "", nlsP->alpha4, &nlsP->alpha4, NULL));
7559566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_alpha5", "", "", nlsP->alpha5, &nlsP->alpha5, NULL));
7569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_nu1", "poor steplength; reduce radius", "", nlsP->nu1, &nlsP->nu1, NULL));
7579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_nu2", "reasonable steplength; leave radius alone", "", nlsP->nu2, &nlsP->nu2, NULL));
7589566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_nu3", "good steplength; increase radius", "", nlsP->nu3, &nlsP->nu3, NULL));
7599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_nu4", "excellent steplength; greatly increase radius", "", nlsP->nu4, &nlsP->nu4, NULL));
7609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_omega1", "", "", nlsP->omega1, &nlsP->omega1, NULL));
7619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_omega2", "", "", nlsP->omega2, &nlsP->omega2, NULL));
7629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_omega3", "", "", nlsP->omega3, &nlsP->omega3, NULL));
7639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_omega4", "", "", nlsP->omega4, &nlsP->omega4, NULL));
7649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_omega5", "", "", nlsP->omega5, &nlsP->omega5, NULL));
7659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_mu1_i", "", "", nlsP->mu1_i, &nlsP->mu1_i, NULL));
7669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_mu2_i", "", "", nlsP->mu2_i, &nlsP->mu2_i, NULL));
7679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_gamma1_i", "", "", nlsP->gamma1_i, &nlsP->gamma1_i, NULL));
7689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_gamma2_i", "", "", nlsP->gamma2_i, &nlsP->gamma2_i, NULL));
7699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_gamma3_i", "", "", nlsP->gamma3_i, &nlsP->gamma3_i, NULL));
7709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_gamma4_i", "", "", nlsP->gamma4_i, &nlsP->gamma4_i, NULL));
7719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_theta_i", "", "", nlsP->theta_i, &nlsP->theta_i, NULL));
7729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_mu1", "", "", nlsP->mu1, &nlsP->mu1, NULL));
7739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_mu2", "", "", nlsP->mu2, &nlsP->mu2, NULL));
7749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_gamma1", "", "", nlsP->gamma1, &nlsP->gamma1, NULL));
7759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_gamma2", "", "", nlsP->gamma2, &nlsP->gamma2, NULL));
7769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_gamma3", "", "", nlsP->gamma3, &nlsP->gamma3, NULL));
7779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_gamma4", "", "", nlsP->gamma4, &nlsP->gamma4, NULL));
7789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_theta", "", "", nlsP->theta, &nlsP->theta, NULL));
7799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_min_radius", "lower bound on initial radius", "", nlsP->min_radius, &nlsP->min_radius, NULL));
7809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_max_radius", "upper bound on radius", "", nlsP->max_radius, &nlsP->max_radius, NULL));
7819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_nls_epsilon", "tolerance used when computing actual and predicted reduction", "", nlsP->epsilon, &nlsP->epsilon, NULL));
782d0609cedSBarry Smith   PetscOptionsHeadEnd();
7839566063dSJacob Faibussowitsch   PetscCall(TaoLineSearchSetFromOptions(tao->linesearch));
7849566063dSJacob Faibussowitsch   PetscCall(KSPSetFromOptions(tao->ksp));
785a7e14dcfSSatish Balay   PetscFunctionReturn(0);
786a7e14dcfSSatish Balay }
787a7e14dcfSSatish Balay 
788a7e14dcfSSatish Balay /*------------------------------------------------------------*/
789*d71ae5a4SJacob Faibussowitsch static PetscErrorCode TaoView_NLS(Tao tao, PetscViewer viewer)
790*d71ae5a4SJacob Faibussowitsch {
791a7e14dcfSSatish Balay   TAO_NLS  *nlsP = (TAO_NLS *)tao->data;
792a7e14dcfSSatish Balay   PetscBool isascii;
793a7e14dcfSSatish Balay 
794a7e14dcfSSatish Balay   PetscFunctionBegin;
7959566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
796a7e14dcfSSatish Balay   if (isascii) {
7979566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
79863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Newton steps: %" PetscInt_FMT "\n", nlsP->newt));
79963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "BFGS steps: %" PetscInt_FMT "\n", nlsP->bfgs));
80063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Gradient steps: %" PetscInt_FMT "\n", nlsP->grad));
801a7e14dcfSSatish Balay 
80263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "nls ksp atol: %" PetscInt_FMT "\n", nlsP->ksp_atol));
80363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "nls ksp rtol: %" PetscInt_FMT "\n", nlsP->ksp_rtol));
80463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "nls ksp ctol: %" PetscInt_FMT "\n", nlsP->ksp_ctol));
80563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "nls ksp negc: %" PetscInt_FMT "\n", nlsP->ksp_negc));
80663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "nls ksp dtol: %" PetscInt_FMT "\n", nlsP->ksp_dtol));
80763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "nls ksp iter: %" PetscInt_FMT "\n", nlsP->ksp_iter));
80863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "nls ksp othr: %" PetscInt_FMT "\n", nlsP->ksp_othr));
8099566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
810a7e14dcfSSatish Balay   }
811a7e14dcfSSatish Balay   PetscFunctionReturn(0);
812a7e14dcfSSatish Balay }
813a7e14dcfSSatish Balay 
814a7e14dcfSSatish Balay /* ---------------------------------------------------------- */
8154aa34175SJason Sarich /*MC
8164aa34175SJason Sarich   TAONLS - Newton's method with linesearch for unconstrained minimization.
8174aa34175SJason Sarich   At each iteration, the Newton line search method solves the symmetric
8184aa34175SJason Sarich   system of equations to obtain the step diretion dk:
8194aa34175SJason Sarich               Hk dk = -gk
8204aa34175SJason Sarich   a More-Thuente line search is applied on the direction dk to approximately
8214aa34175SJason Sarich   solve
8224aa34175SJason Sarich               min_t f(xk + t d_k)
8234aa34175SJason Sarich 
8244aa34175SJason Sarich     Options Database Keys:
8259d0a60b2SAlp Dener + -tao_nls_init_type - "constant","direction","interpolation"
8264aa34175SJason Sarich . -tao_nls_update_type - "step","direction","interpolation"
8274aa34175SJason Sarich . -tao_nls_sval - perturbation starting value
8284aa34175SJason Sarich . -tao_nls_imin - minimum initial perturbation
8294aa34175SJason Sarich . -tao_nls_imax - maximum initial perturbation
8304aa34175SJason Sarich . -tao_nls_pmin - minimum perturbation
8314aa34175SJason Sarich . -tao_nls_pmax - maximum perturbation
8324aa34175SJason Sarich . -tao_nls_pgfac - growth factor
8334aa34175SJason Sarich . -tao_nls_psfac - shrink factor
8344aa34175SJason Sarich . -tao_nls_imfac - initial merit factor
8354aa34175SJason Sarich . -tao_nls_pmgfac - merit growth factor
8364aa34175SJason Sarich . -tao_nls_pmsfac - merit shrink factor
8374aa34175SJason Sarich . -tao_nls_eta1 - poor steplength; reduce radius
8384aa34175SJason Sarich . -tao_nls_eta2 - reasonable steplength; leave radius
8394aa34175SJason Sarich . -tao_nls_eta3 - good steplength; increase readius
8404aa34175SJason Sarich . -tao_nls_eta4 - excellent steplength; greatly increase radius
8414aa34175SJason Sarich . -tao_nls_alpha1 - alpha1 reduction
8424aa34175SJason Sarich . -tao_nls_alpha2 - alpha2 reduction
8434aa34175SJason Sarich . -tao_nls_alpha3 - alpha3 reduction
8444aa34175SJason Sarich . -tao_nls_alpha4 - alpha4 reduction
8454aa34175SJason Sarich . -tao_nls_alpha - alpha5 reduction
8464aa34175SJason Sarich . -tao_nls_mu1 - mu1 interpolation update
8474aa34175SJason Sarich . -tao_nls_mu2 - mu2 interpolation update
8484aa34175SJason Sarich . -tao_nls_gamma1 - gamma1 interpolation update
8494aa34175SJason Sarich . -tao_nls_gamma2 - gamma2 interpolation update
8504aa34175SJason Sarich . -tao_nls_gamma3 - gamma3 interpolation update
8514aa34175SJason Sarich . -tao_nls_gamma4 - gamma4 interpolation update
8524aa34175SJason Sarich . -tao_nls_theta - theta interpolation update
8534aa34175SJason Sarich . -tao_nls_omega1 - omega1 step update
8544aa34175SJason Sarich . -tao_nls_omega2 - omega2 step update
8554aa34175SJason Sarich . -tao_nls_omega3 - omega3 step update
8564aa34175SJason Sarich . -tao_nls_omega4 - omega4 step update
8574aa34175SJason Sarich . -tao_nls_omega5 - omega5 step update
8581522df2eSJason Sarich . -tao_nls_mu1_i -  mu1 interpolation init factor
8591522df2eSJason Sarich . -tao_nls_mu2_i -  mu2 interpolation init factor
8601522df2eSJason Sarich . -tao_nls_gamma1_i -  gamma1 interpolation init factor
8611522df2eSJason Sarich . -tao_nls_gamma2_i -  gamma2 interpolation init factor
8621522df2eSJason Sarich . -tao_nls_gamma3_i -  gamma3 interpolation init factor
8631522df2eSJason Sarich . -tao_nls_gamma4_i -  gamma4 interpolation init factor
8641522df2eSJason Sarich - -tao_nls_theta_i -  theta interpolation init factor
8651eb8069cSJason Sarich 
8661eb8069cSJason Sarich   Level: beginner
8671522df2eSJason Sarich M*/
8684aa34175SJason Sarich 
869*d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode TaoCreate_NLS(Tao tao)
870*d71ae5a4SJacob Faibussowitsch {
871a7e14dcfSSatish Balay   TAO_NLS    *nlsP;
8728caf6e8cSBarry Smith   const char *morethuente_type = TAOLINESEARCHMT;
873a7e14dcfSSatish Balay 
874a7e14dcfSSatish Balay   PetscFunctionBegin;
8754dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&nlsP));
876a7e14dcfSSatish Balay 
877a7e14dcfSSatish Balay   tao->ops->setup          = TaoSetUp_NLS;
878a7e14dcfSSatish Balay   tao->ops->solve          = TaoSolve_NLS;
879a7e14dcfSSatish Balay   tao->ops->view           = TaoView_NLS;
880a7e14dcfSSatish Balay   tao->ops->setfromoptions = TaoSetFromOptions_NLS;
881a7e14dcfSSatish Balay   tao->ops->destroy        = TaoDestroy_NLS;
882a7e14dcfSSatish Balay 
8836552cf8aSJason Sarich   /* Override default settings (unless already changed) */
8846552cf8aSJason Sarich   if (!tao->max_it_changed) tao->max_it = 50;
8856552cf8aSJason Sarich   if (!tao->trust0_changed) tao->trust0 = 100.0;
8866552cf8aSJason Sarich 
887a7e14dcfSSatish Balay   tao->data = (void *)nlsP;
888a7e14dcfSSatish Balay 
889a7e14dcfSSatish Balay   nlsP->sval  = 0.0;
890a7e14dcfSSatish Balay   nlsP->imin  = 1.0e-4;
891a7e14dcfSSatish Balay   nlsP->imax  = 1.0e+2;
892a7e14dcfSSatish Balay   nlsP->imfac = 1.0e-1;
893a7e14dcfSSatish Balay 
894a7e14dcfSSatish Balay   nlsP->pmin   = 1.0e-12;
895a7e14dcfSSatish Balay   nlsP->pmax   = 1.0e+2;
896a7e14dcfSSatish Balay   nlsP->pgfac  = 1.0e+1;
897a7e14dcfSSatish Balay   nlsP->psfac  = 4.0e-1;
898a7e14dcfSSatish Balay   nlsP->pmgfac = 1.0e-1;
899a7e14dcfSSatish Balay   nlsP->pmsfac = 1.0e-1;
900a7e14dcfSSatish Balay 
901a7e14dcfSSatish Balay   /*  Default values for trust-region radius update based on steplength */
902a7e14dcfSSatish Balay   nlsP->nu1 = 0.25;
903a7e14dcfSSatish Balay   nlsP->nu2 = 0.50;
904a7e14dcfSSatish Balay   nlsP->nu3 = 1.00;
905a7e14dcfSSatish Balay   nlsP->nu4 = 1.25;
906a7e14dcfSSatish Balay 
907a7e14dcfSSatish Balay   nlsP->omega1 = 0.25;
908a7e14dcfSSatish Balay   nlsP->omega2 = 0.50;
909a7e14dcfSSatish Balay   nlsP->omega3 = 1.00;
910a7e14dcfSSatish Balay   nlsP->omega4 = 2.00;
911a7e14dcfSSatish Balay   nlsP->omega5 = 4.00;
912a7e14dcfSSatish Balay 
913a7e14dcfSSatish Balay   /*  Default values for trust-region radius update based on reduction */
914a7e14dcfSSatish Balay   nlsP->eta1 = 1.0e-4;
915a7e14dcfSSatish Balay   nlsP->eta2 = 0.25;
916a7e14dcfSSatish Balay   nlsP->eta3 = 0.50;
917a7e14dcfSSatish Balay   nlsP->eta4 = 0.90;
918a7e14dcfSSatish Balay 
919a7e14dcfSSatish Balay   nlsP->alpha1 = 0.25;
920a7e14dcfSSatish Balay   nlsP->alpha2 = 0.50;
921a7e14dcfSSatish Balay   nlsP->alpha3 = 1.00;
922a7e14dcfSSatish Balay   nlsP->alpha4 = 2.00;
923a7e14dcfSSatish Balay   nlsP->alpha5 = 4.00;
924a7e14dcfSSatish Balay 
925a7e14dcfSSatish Balay   /*  Default values for trust-region radius update based on interpolation */
926a7e14dcfSSatish Balay   nlsP->mu1 = 0.10;
927a7e14dcfSSatish Balay   nlsP->mu2 = 0.50;
928a7e14dcfSSatish Balay 
929a7e14dcfSSatish Balay   nlsP->gamma1 = 0.25;
930a7e14dcfSSatish Balay   nlsP->gamma2 = 0.50;
931a7e14dcfSSatish Balay   nlsP->gamma3 = 2.00;
932a7e14dcfSSatish Balay   nlsP->gamma4 = 4.00;
933a7e14dcfSSatish Balay 
934a7e14dcfSSatish Balay   nlsP->theta = 0.05;
935a7e14dcfSSatish Balay 
936a7e14dcfSSatish Balay   /*  Default values for trust region initialization based on interpolation */
937a7e14dcfSSatish Balay   nlsP->mu1_i = 0.35;
938a7e14dcfSSatish Balay   nlsP->mu2_i = 0.50;
939a7e14dcfSSatish Balay 
940a7e14dcfSSatish Balay   nlsP->gamma1_i = 0.0625;
941a7e14dcfSSatish Balay   nlsP->gamma2_i = 0.5;
942a7e14dcfSSatish Balay   nlsP->gamma3_i = 2.0;
943a7e14dcfSSatish Balay   nlsP->gamma4_i = 5.0;
944a7e14dcfSSatish Balay 
945a7e14dcfSSatish Balay   nlsP->theta_i = 0.25;
946a7e14dcfSSatish Balay 
947a7e14dcfSSatish Balay   /*  Remaining parameters */
948a7e14dcfSSatish Balay   nlsP->min_radius = 1.0e-10;
949a7e14dcfSSatish Balay   nlsP->max_radius = 1.0e10;
950a7e14dcfSSatish Balay   nlsP->epsilon    = 1.0e-6;
951a7e14dcfSSatish Balay 
952a7e14dcfSSatish Balay   nlsP->init_type   = NLS_INIT_INTERPOLATION;
953a7e14dcfSSatish Balay   nlsP->update_type = NLS_UPDATE_STEP;
954a7e14dcfSSatish Balay 
9559566063dSJacob Faibussowitsch   PetscCall(TaoLineSearchCreate(((PetscObject)tao)->comm, &tao->linesearch));
9569566063dSJacob Faibussowitsch   PetscCall(PetscObjectIncrementTabLevel((PetscObject)tao->linesearch, (PetscObject)tao, 1));
9579566063dSJacob Faibussowitsch   PetscCall(TaoLineSearchSetType(tao->linesearch, morethuente_type));
9589566063dSJacob Faibussowitsch   PetscCall(TaoLineSearchUseTaoRoutines(tao->linesearch, tao));
9599566063dSJacob Faibussowitsch   PetscCall(TaoLineSearchSetOptionsPrefix(tao->linesearch, tao->hdr.prefix));
960a7e14dcfSSatish Balay 
961a7e14dcfSSatish Balay   /*  Set linear solver to default for symmetric matrices */
9629566063dSJacob Faibussowitsch   PetscCall(KSPCreate(((PetscObject)tao)->comm, &tao->ksp));
9639566063dSJacob Faibussowitsch   PetscCall(PetscObjectIncrementTabLevel((PetscObject)tao->ksp, (PetscObject)tao, 1));
9649566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(tao->ksp, tao->hdr.prefix));
9659566063dSJacob Faibussowitsch   PetscCall(KSPAppendOptionsPrefix(tao->ksp, "tao_nls_"));
9669566063dSJacob Faibussowitsch   PetscCall(KSPSetType(tao->ksp, KSPSTCG));
967a7e14dcfSSatish Balay   PetscFunctionReturn(0);
968a7e14dcfSSatish Balay }
969