xref: /petsc/src/tao/unconstrained/impls/lmvm/lmvm.c (revision 0ad3a4972f8208d0437d2072e146ab5cff37228d)
1ba92ff59SBarry Smith #include <petsctaolinesearch.h>
2aaa7dc30SBarry Smith #include <../src/tao/unconstrained/impls/lmvm/lmvm.h>
313b46278SAlp Dener #include <../src/tao/bound/impls/blmvm/blmvm.h>
4a7e14dcfSSatish Balay 
5cd929ea3SAlp Dener #define LMVM_STEP_BFGS     0
6cd929ea3SAlp Dener #define LMVM_STEP_GRAD     1
7a7e14dcfSSatish Balay 
8441846f8SBarry Smith static PetscErrorCode TaoSolve_LMVM(Tao tao)
9a7e14dcfSSatish Balay {
10a7e14dcfSSatish Balay   TAO_LMVM                     *lmP = (TAO_LMVM *)tao->data;
11a7e14dcfSSatish Balay   PetscReal                    f, fold, gdx, gnorm;
12a7e14dcfSSatish Balay   PetscReal                    step = 1.0;
13a7e14dcfSSatish Balay   PetscErrorCode               ierr;
14cd929ea3SAlp Dener   PetscInt                     stepType = LMVM_STEP_GRAD, nupdates;
15e4cb33bbSBarry Smith   TaoLineSearchConvergedReason ls_status = TAOLINESEARCH_CONTINUE_ITERATING;
16a7e14dcfSSatish Balay 
17a7e14dcfSSatish Balay   PetscFunctionBegin;
18a7e14dcfSSatish Balay 
19a7e14dcfSSatish Balay   if (tao->XL || tao->XU || tao->ops->computebounds) {
20a7e14dcfSSatish Balay     ierr = PetscPrintf(((PetscObject)tao)->comm,"WARNING: Variable bounds have been set but will be ignored by lmvm algorithm\n");CHKERRQ(ierr);
21a7e14dcfSSatish Balay   }
22a7e14dcfSSatish Balay 
23a7e14dcfSSatish Balay   /*  Check convergence criteria */
24a7e14dcfSSatish Balay   ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &f, tao->gradient);CHKERRQ(ierr);
25a9603a14SPatrick Farrell   ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&gnorm);CHKERRQ(ierr);
26a9603a14SPatrick Farrell 
2787f595a5SBarry Smith   if (PetscIsInfOrNanReal(f) || PetscIsInfOrNanReal(gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN");
28a7e14dcfSSatish Balay 
293ecd9318SAlp Dener   tao->reason = TAO_CONTINUE_ITERATING;
303ecd9318SAlp Dener   ierr = TaoLogConvergenceHistory(tao,f,gnorm,0.0,tao->ksp_its);CHKERRQ(ierr);
313ecd9318SAlp Dener   ierr = TaoMonitor(tao,tao->niter,f,gnorm,0.0,step);CHKERRQ(ierr);
323ecd9318SAlp Dener   ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
333ecd9318SAlp Dener   if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0);
34a7e14dcfSSatish Balay 
35a7e14dcfSSatish Balay   /*  Set counter for gradient/reset steps */
36cd929ea3SAlp Dener   if (!lmP->recycle) {
37a7e14dcfSSatish Balay     lmP->bfgs = 0;
38a7e14dcfSSatish Balay     lmP->grad = 0;
39cd929ea3SAlp Dener     ierr = MatLMVMReset(lmP->M, PETSC_FALSE); CHKERRQ(ierr);
40de6ffafeSAlp Dener   }
41a7e14dcfSSatish Balay 
42a7e14dcfSSatish Balay   /*  Have not converged; continue with Newton method */
433ecd9318SAlp Dener   while (tao->reason == TAO_CONTINUE_ITERATING) {
44a7e14dcfSSatish Balay     /*  Compute direction */
45cd929ea3SAlp Dener     if (lmP->H0) {
46cd929ea3SAlp Dener       ierr = MatLMVMSetJ0(lmP->M, lmP->H0);CHKERRQ(ierr);
47cd929ea3SAlp Dener       stepType = LMVM_STEP_BFGS;
48*0ad3a497SAlp Dener     } else if (!lmP->no_scale) {
49*0ad3a497SAlp Dener       ierr = MatLMVMSetJ0(lmP->M, lmP->Mscale);CHKERRQ(ierr);
50cd929ea3SAlp Dener     }
51a7e14dcfSSatish Balay     ierr = MatLMVMUpdate(lmP->M,tao->solution,tao->gradient);CHKERRQ(ierr);
52cd929ea3SAlp Dener     ierr = MatSolve(lmP->M, tao->gradient, lmP->D);CHKERRQ(ierr);
53cd929ea3SAlp Dener     ierr = MatLMVMGetUpdateCount(lmP->M, &nupdates); CHKERRQ(ierr);
54cd929ea3SAlp Dener     if (nupdates > 0) stepType = LMVM_STEP_BFGS;
55a7e14dcfSSatish Balay 
56a7e14dcfSSatish Balay     /*  Check for success (descent direction) */
57a7e14dcfSSatish Balay     ierr = VecDot(lmP->D, tao->gradient, &gdx);CHKERRQ(ierr);
58a7e14dcfSSatish Balay     if ((gdx <= 0.0) || PetscIsInfOrNanReal(gdx)) {
59a7e14dcfSSatish Balay       /* Step is not descent or direction produced not a number
60a7e14dcfSSatish Balay          We can assert bfgsUpdates > 1 in this case because
61a7e14dcfSSatish Balay          the first solve produces the scaled gradient direction,
62a7e14dcfSSatish Balay          which is guaranteed to be descent
63a7e14dcfSSatish Balay 
64a7e14dcfSSatish Balay          Use steepest descent direction (scaled)
65a7e14dcfSSatish Balay       */
66a7e14dcfSSatish Balay 
67cd929ea3SAlp Dener       ierr = MatLMVMReset(lmP->M, PETSC_FALSE);CHKERRQ(ierr);
68*0ad3a497SAlp Dener       ierr = MatLMVMClearJ0(lmP->M);CHKERRQ(ierr);
69a7e14dcfSSatish Balay       ierr = MatLMVMUpdate(lmP->M, tao->solution, tao->gradient);CHKERRQ(ierr);
70cd929ea3SAlp Dener       ierr = MatSolve(lmP->M,tao->gradient, lmP->D);CHKERRQ(ierr);
71a7e14dcfSSatish Balay 
72a7e14dcfSSatish Balay       /* On a reset, the direction cannot be not a number; it is a
73a7e14dcfSSatish Balay          scaled gradient step.  No need to check for this condition. */
74cd929ea3SAlp Dener       stepType = LMVM_STEP_GRAD;
75a7e14dcfSSatish Balay     }
76a7e14dcfSSatish Balay     ierr = VecScale(lmP->D, -1.0);CHKERRQ(ierr);
77a7e14dcfSSatish Balay 
78a7e14dcfSSatish Balay     /*  Perform the linesearch */
79a7e14dcfSSatish Balay     fold = f;
80a7e14dcfSSatish Balay     ierr = VecCopy(tao->solution, lmP->Xold);CHKERRQ(ierr);
81a7e14dcfSSatish Balay     ierr = VecCopy(tao->gradient, lmP->Gold);CHKERRQ(ierr);
82a7e14dcfSSatish Balay 
83a7e14dcfSSatish Balay     ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &f, tao->gradient, lmP->D, &step,&ls_status);CHKERRQ(ierr);
84a7e14dcfSSatish Balay     ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
85a7e14dcfSSatish Balay 
86cd929ea3SAlp Dener     if (ls_status != TAOLINESEARCH_SUCCESS && ls_status != TAOLINESEARCH_SUCCESS_USER && (stepType != LMVM_STEP_GRAD)) {
87a7e14dcfSSatish Balay       /*  Reset factors and use scaled gradient step */
88a7e14dcfSSatish Balay       f = fold;
89a7e14dcfSSatish Balay       ierr = VecCopy(lmP->Xold, tao->solution);CHKERRQ(ierr);
90a7e14dcfSSatish Balay       ierr = VecCopy(lmP->Gold, tao->gradient);CHKERRQ(ierr);
91a7e14dcfSSatish Balay 
92a7e14dcfSSatish Balay       /*  Failed to obtain acceptable iterate with BFGS step */
93a7e14dcfSSatish Balay       /*  Attempt to use the scaled gradient direction */
94a7e14dcfSSatish Balay 
95cd929ea3SAlp Dener       ierr = MatLMVMReset(lmP->M, PETSC_FALSE);CHKERRQ(ierr);
96*0ad3a497SAlp Dener       ierr = MatLMVMClearJ0(lmP->M);CHKERRQ(ierr);
97a7e14dcfSSatish Balay       ierr = MatLMVMUpdate(lmP->M, tao->solution, tao->gradient);CHKERRQ(ierr);
98cd929ea3SAlp Dener       ierr = MatSolve(lmP->M, tao->solution, tao->gradient);CHKERRQ(ierr);
99a7e14dcfSSatish Balay 
100a7e14dcfSSatish Balay       /* On a reset, the direction cannot be not a number; it is a
101a7e14dcfSSatish Balay           scaled gradient step.  No need to check for this condition. */
102cd929ea3SAlp Dener       stepType = LMVM_STEP_GRAD;
103a7e14dcfSSatish Balay       ierr = VecScale(lmP->D, -1.0);CHKERRQ(ierr);
104a7e14dcfSSatish Balay 
105a7e14dcfSSatish Balay       /*  Perform the linesearch */
106a7e14dcfSSatish Balay       ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &f, tao->gradient, lmP->D, &step, &ls_status);CHKERRQ(ierr);
107a7e14dcfSSatish Balay       ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
108a7e14dcfSSatish Balay     }
109a7e14dcfSSatish Balay 
11087f595a5SBarry Smith     if (ls_status != TAOLINESEARCH_SUCCESS && ls_status != TAOLINESEARCH_SUCCESS_USER) {
111a7e14dcfSSatish Balay       /*  Failed to find an improving point */
112a7e14dcfSSatish Balay       f = fold;
113a7e14dcfSSatish Balay       ierr = VecCopy(lmP->Xold, tao->solution);CHKERRQ(ierr);
114a7e14dcfSSatish Balay       ierr = VecCopy(lmP->Gold, tao->gradient);CHKERRQ(ierr);
115a7e14dcfSSatish Balay       step = 0.0;
116a7e14dcfSSatish Balay       tao->reason = TAO_DIVERGED_LS_FAILURE;
117cd929ea3SAlp Dener     } else {
118cd929ea3SAlp Dener       /* LS found valid step, so tally up step type */
119cd929ea3SAlp Dener       switch (stepType) {
120cd929ea3SAlp Dener       case LMVM_STEP_BFGS:
121cd929ea3SAlp Dener         ++lmP->bfgs;
122cd929ea3SAlp Dener         break;
123cd929ea3SAlp Dener       case LMVM_STEP_GRAD:
124cd929ea3SAlp Dener         ++lmP->grad;
125cd929ea3SAlp Dener         break;
126cd929ea3SAlp Dener       default:
127cd929ea3SAlp Dener         break;
128cd929ea3SAlp Dener       }
129cd929ea3SAlp Dener       /*  Compute new gradient norm */
130cd929ea3SAlp Dener       ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&gnorm);CHKERRQ(ierr);
131a7e14dcfSSatish Balay     }
132a9603a14SPatrick Farrell 
133cd929ea3SAlp Dener     /* Check convergence */
1348931d482SJason Sarich     tao->niter++;
1353ecd9318SAlp Dener     ierr = TaoLogConvergenceHistory(tao,f,gnorm,0.0,tao->ksp_its);CHKERRQ(ierr);
1363ecd9318SAlp Dener     ierr = TaoMonitor(tao,tao->niter,f,gnorm,0.0,step);CHKERRQ(ierr);
1373ecd9318SAlp Dener     ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
138a7e14dcfSSatish Balay   }
139a7e14dcfSSatish Balay   PetscFunctionReturn(0);
140a7e14dcfSSatish Balay }
14187f595a5SBarry Smith 
142441846f8SBarry Smith static PetscErrorCode TaoSetUp_LMVM(Tao tao)
143a7e14dcfSSatish Balay {
144a7e14dcfSSatish Balay   TAO_LMVM       *lmP = (TAO_LMVM *)tao->data;
145a7e14dcfSSatish Balay   PetscInt       n,N;
146a7e14dcfSSatish Balay   PetscErrorCode ierr;
147*0ad3a497SAlp Dener   PetscBool      is_spd, is_symbrdn;
148a7e14dcfSSatish Balay 
149a7e14dcfSSatish Balay   PetscFunctionBegin;
150a7e14dcfSSatish Balay   /* Existence of tao->solution checked in TaoSetUp() */
151a7e14dcfSSatish Balay   if (!tao->gradient) {ierr = VecDuplicate(tao->solution,&tao->gradient);CHKERRQ(ierr);  }
152a7e14dcfSSatish Balay   if (!tao->stepdirection) {ierr = VecDuplicate(tao->solution,&tao->stepdirection);CHKERRQ(ierr);  }
153a7e14dcfSSatish Balay   if (!lmP->D) {ierr = VecDuplicate(tao->solution,&lmP->D);CHKERRQ(ierr);  }
154a7e14dcfSSatish Balay   if (!lmP->Xold) {ierr = VecDuplicate(tao->solution,&lmP->Xold);CHKERRQ(ierr);  }
155a7e14dcfSSatish Balay   if (!lmP->Gold) {ierr = VecDuplicate(tao->solution,&lmP->Gold);CHKERRQ(ierr);  }
156a7e14dcfSSatish Balay 
157a7e14dcfSSatish Balay   /*  Create matrix for the limited memory approximation */
158a7e14dcfSSatish Balay   ierr = VecGetLocalSize(tao->solution,&n);CHKERRQ(ierr);
159a7e14dcfSSatish Balay   ierr = VecGetSize(tao->solution,&N);CHKERRQ(ierr);
160cd929ea3SAlp Dener   ierr = MatSetSizes(lmP->M, n, n, N, N);CHKERRQ(ierr);
161cd929ea3SAlp Dener   ierr = MatLMVMAllocate(lmP->M,tao->solution,tao->gradient);CHKERRQ(ierr);
162*0ad3a497SAlp Dener   ierr = MatGetOption(lmP->M, MAT_SPD, &is_spd);CHKERRQ(ierr);
163*0ad3a497SAlp Dener   if (!is_spd) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "LMVM matrix is not symmetric positive-definite.");
164*0ad3a497SAlp Dener   ierr = PetscObjectTypeCompare((PetscObject)lmP->M, MATLMVMSYMBRDN, &is_symbrdn);
165*0ad3a497SAlp Dener   if (is_symbrdn) lmP->no_scale = PETSC_TRUE; /* makes no sense to scale L-SymBrdn with SymBrdn diagonal */
166a9603a14SPatrick Farrell 
167a9603a14SPatrick Farrell   /* If the user has set a matrix to solve as the initial H0, set the options prefix here, and set up the KSP */
168a9603a14SPatrick Farrell   if (lmP->H0) {
169cd929ea3SAlp Dener     ierr = MatLMVMSetJ0(lmP->M, lmP->H0);CHKERRQ(ierr);
170*0ad3a497SAlp Dener   } else if (!lmP->no_scale) {
171*0ad3a497SAlp Dener     if (!lmP->Mscale) {
172*0ad3a497SAlp Dener       ierr = MatCreateLMVMDiagBrdn(PetscObjectComm((PetscObject)lmP->M), n, N, &lmP->Mscale);CHKERRQ(ierr);
173*0ad3a497SAlp Dener       ierr = MatSetOptionsPrefix(lmP->Mscale, "tao_lmvm_scale_");CHKERRQ(ierr);
174*0ad3a497SAlp Dener       ierr = MatLMVMAllocate(lmP->Mscale, tao->solution, tao->gradient);CHKERRQ(ierr);
175*0ad3a497SAlp Dener     }
176*0ad3a497SAlp Dener     ierr = MatLMVMSetJ0(lmP->M, lmP->Mscale);CHKERRQ(ierr);
177a9603a14SPatrick Farrell   }
178a9603a14SPatrick Farrell 
179a7e14dcfSSatish Balay   PetscFunctionReturn(0);
180a7e14dcfSSatish Balay }
181a7e14dcfSSatish Balay 
182a7e14dcfSSatish Balay /* ---------------------------------------------------------- */
183441846f8SBarry Smith static PetscErrorCode TaoDestroy_LMVM(Tao tao)
184a7e14dcfSSatish Balay {
185a7e14dcfSSatish Balay   TAO_LMVM       *lmP = (TAO_LMVM *)tao->data;
186a7e14dcfSSatish Balay   PetscErrorCode ierr;
187a7e14dcfSSatish Balay 
188a7e14dcfSSatish Balay   PetscFunctionBegin;
189a7e14dcfSSatish Balay   if (tao->setupcalled) {
190a7e14dcfSSatish Balay     ierr = VecDestroy(&lmP->Xold);CHKERRQ(ierr);
191a7e14dcfSSatish Balay     ierr = VecDestroy(&lmP->Gold);CHKERRQ(ierr);
192a7e14dcfSSatish Balay     ierr = VecDestroy(&lmP->D);CHKERRQ(ierr);
193a7e14dcfSSatish Balay   }
194cd929ea3SAlp Dener   ierr = MatDestroy(&lmP->M);CHKERRQ(ierr);
195a9603a14SPatrick Farrell   if (lmP->H0) {
196a9603a14SPatrick Farrell     ierr = PetscObjectDereference((PetscObject)lmP->H0);CHKERRQ(ierr);
197a9603a14SPatrick Farrell   }
198*0ad3a497SAlp Dener   if (lmP->Mscale) {
199*0ad3a497SAlp Dener     ierr = MatDestroy(&lmP->Mscale);CHKERRQ(ierr);
200*0ad3a497SAlp Dener   }
201a7e14dcfSSatish Balay   ierr = PetscFree(tao->data);CHKERRQ(ierr);
202a9603a14SPatrick Farrell 
203a7e14dcfSSatish Balay   PetscFunctionReturn(0);
204a7e14dcfSSatish Balay }
205a7e14dcfSSatish Balay 
206a7e14dcfSSatish Balay /*------------------------------------------------------------*/
2074416b707SBarry Smith static PetscErrorCode TaoSetFromOptions_LMVM(PetscOptionItems *PetscOptionsObject,Tao tao)
208a7e14dcfSSatish Balay {
209cd929ea3SAlp Dener   TAO_LMVM       *lm = (TAO_LMVM *)tao->data;
210a7e14dcfSSatish Balay   PetscErrorCode ierr;
211a7e14dcfSSatish Balay 
212a7e14dcfSSatish Balay   PetscFunctionBegin;
2131a1499c8SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"Limited-memory variable-metric method for unconstrained optimization");CHKERRQ(ierr);
214cd929ea3SAlp Dener   ierr = PetscOptionsBool("-tao_lmvm_recycle","enable recycling of the BFGS matrix between subsequent TaoSolve() calls","",lm->recycle,&lm->recycle,NULL);CHKERRQ(ierr);
215*0ad3a497SAlp Dener   ierr = PetscOptionsBool("-tao_lmvm_no_scale","(developer) disable the diagonal Broyden scaling of the BFGS approximation","",lm->no_scale,&lm->no_scale,NULL);CHKERRQ(ierr);
216114d2d62SAlp Dener   ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr);
217cd929ea3SAlp Dener   ierr = MatSetFromOptions(lm->M);CHKERRQ(ierr);
218288b7216SAlp Dener   ierr = PetscOptionsTail();CHKERRQ(ierr);
219a7e14dcfSSatish Balay   PetscFunctionReturn(0);
220a7e14dcfSSatish Balay }
221a7e14dcfSSatish Balay 
222a7e14dcfSSatish Balay /*------------------------------------------------------------*/
223441846f8SBarry Smith static PetscErrorCode TaoView_LMVM(Tao tao, PetscViewer viewer)
224a7e14dcfSSatish Balay {
225a7e14dcfSSatish Balay   TAO_LMVM       *lm = (TAO_LMVM *)tao->data;
226cd929ea3SAlp Dener   PetscBool      isascii;
2274d6623b4SAlp Dener   PetscInt       recycled_its;
228a7e14dcfSSatish Balay   PetscErrorCode ierr;
229a7e14dcfSSatish Balay 
230a7e14dcfSSatish Balay   PetscFunctionBegin;
231a7e14dcfSSatish Balay   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr);
232a7e14dcfSSatish Balay   if (isascii) {
233a7e14dcfSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer, "  Gradient steps: %D\n", lm->grad);CHKERRQ(ierr);
234cd929ea3SAlp Dener     if (lm->recycle) {
235288b7216SAlp Dener       ierr = PetscViewerASCIIPrintf(viewer, "  Recycle: on\n");CHKERRQ(ierr);
236cd929ea3SAlp Dener       recycled_its = lm->bfgs + lm->grad;
2374d6623b4SAlp Dener       ierr = PetscViewerASCIIPrintf(viewer, "  Total recycled iterations: %D\n", recycled_its);CHKERRQ(ierr);
238a0bfee83SAlp Dener     }
239a7e14dcfSSatish Balay   }
240a7e14dcfSSatish Balay   PetscFunctionReturn(0);
241a7e14dcfSSatish Balay }
242a7e14dcfSSatish Balay 
243a7e14dcfSSatish Balay /* ---------------------------------------------------------- */
244a7e14dcfSSatish Balay 
2454aa34175SJason Sarich /*MC
2464aa34175SJason Sarich   TAOLMVM - Limited Memory Variable Metric method is a quasi-Newton
2474aa34175SJason Sarich   optimization solver for unconstrained minimization. It solves
2484aa34175SJason Sarich   the Newton step
2494aa34175SJason Sarich           Hkdk = - gk
2504aa34175SJason Sarich 
2514aa34175SJason Sarich   using an approximation Bk in place of Hk, where Bk is composed using
2524aa34175SJason Sarich   the BFGS update formula. A More-Thuente line search is then used
2534aa34175SJason Sarich   to computed the steplength in the dk direction
254*0ad3a497SAlp Dener 
2554aa34175SJason Sarich   Options Database Keys:
256cd929ea3SAlp Dener .   -tao_lmvm_recycle - enable recycling LMVM updates between TaoSolve() calls
257*0ad3a497SAlp Dener .   -tao_lmvm_no_scale - (developer) disables diagonal Broyden scaling on the LMVM approximation
2584aa34175SJason Sarich 
2591eb8069cSJason Sarich   Level: beginner
2604aa34175SJason Sarich M*/
2614aa34175SJason Sarich 
262728e0ed0SBarry Smith PETSC_EXTERN PetscErrorCode TaoCreate_LMVM(Tao tao)
263a7e14dcfSSatish Balay {
264a7e14dcfSSatish Balay   TAO_LMVM       *lmP;
2658caf6e8cSBarry Smith   const char     *morethuente_type = TAOLINESEARCHMT;
266a7e14dcfSSatish Balay   PetscErrorCode ierr;
267a7e14dcfSSatish Balay 
268a7e14dcfSSatish Balay   PetscFunctionBegin;
269a7e14dcfSSatish Balay   tao->ops->setup = TaoSetUp_LMVM;
270a7e14dcfSSatish Balay   tao->ops->solve = TaoSolve_LMVM;
271a7e14dcfSSatish Balay   tao->ops->view = TaoView_LMVM;
272a7e14dcfSSatish Balay   tao->ops->setfromoptions = TaoSetFromOptions_LMVM;
273a7e14dcfSSatish Balay   tao->ops->destroy = TaoDestroy_LMVM;
274a7e14dcfSSatish Balay 
2753c9e27cfSGeoffrey Irving   ierr = PetscNewLog(tao,&lmP);CHKERRQ(ierr);
276a7e14dcfSSatish Balay   lmP->D = 0;
277a7e14dcfSSatish Balay   lmP->M = 0;
278a7e14dcfSSatish Balay   lmP->Xold = 0;
279a7e14dcfSSatish Balay   lmP->Gold = 0;
280a9603a14SPatrick Farrell   lmP->H0   = NULL;
281cd929ea3SAlp Dener   lmP->recycle = PETSC_FALSE;
282*0ad3a497SAlp Dener   lmP->no_scale = PETSC_FALSE;
283a7e14dcfSSatish Balay 
284a7e14dcfSSatish Balay   tao->data = (void*)lmP;
2856552cf8aSJason Sarich   /* Override default settings (unless already changed) */
2866552cf8aSJason Sarich   if (!tao->max_it_changed) tao->max_it = 2000;
2876552cf8aSJason Sarich   if (!tao->max_funcs_changed) tao->max_funcs = 4000;
288a7e14dcfSSatish Balay 
289a7e14dcfSSatish Balay   ierr = TaoLineSearchCreate(((PetscObject)tao)->comm,&tao->linesearch);CHKERRQ(ierr);
29063b15415SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)tao->linesearch, (PetscObject)tao, 1);CHKERRQ(ierr);
291a7e14dcfSSatish Balay   ierr = TaoLineSearchSetType(tao->linesearch,morethuente_type);CHKERRQ(ierr);
292441846f8SBarry Smith   ierr = TaoLineSearchUseTaoRoutines(tao->linesearch,tao);CHKERRQ(ierr);
2935d527766SPatrick Farrell   ierr = TaoLineSearchSetOptionsPrefix(tao->linesearch,tao->hdr.prefix);CHKERRQ(ierr);
294cd929ea3SAlp Dener 
295cd929ea3SAlp Dener   ierr = KSPInitializePackage();CHKERRQ(ierr);
296cd929ea3SAlp Dener   ierr = MatCreate(((PetscObject)tao)->comm, &lmP->M);CHKERRQ(ierr);
297cd929ea3SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)lmP->M, (PetscObject)tao, 1);CHKERRQ(ierr);
29878e4361aSAlp Dener   ierr = MatSetType(lmP->M, MATLMVMBFGS);CHKERRQ(ierr);
299cd929ea3SAlp Dener   ierr = MatSetOptionsPrefix(lmP->M, "tao_lmvm_");CHKERRQ(ierr);
300a7e14dcfSSatish Balay   PetscFunctionReturn(0);
301a7e14dcfSSatish Balay }
30213b46278SAlp Dener 
30313b46278SAlp Dener PETSC_EXTERN PetscErrorCode TaoLMVMSetH0(Tao tao, Mat H0)
30413b46278SAlp Dener {
30513b46278SAlp Dener   TAO_LMVM       *lmP;
30613b46278SAlp Dener   TAO_BLMVM      *blmP;
30713b46278SAlp Dener   const TaoType  type;
30813b46278SAlp Dener   PetscBool      is_lmvm, is_blmvm;
30913b46278SAlp Dener   PetscErrorCode ierr;
31013b46278SAlp Dener 
31113b46278SAlp Dener   ierr = TaoGetType(tao, &type);CHKERRQ(ierr);
31213b46278SAlp Dener   ierr = PetscStrcmp(type, TAOLMVM,  &is_lmvm);CHKERRQ(ierr);
31313b46278SAlp Dener   ierr = PetscStrcmp(type, TAOBLMVM, &is_blmvm);CHKERRQ(ierr);
31413b46278SAlp Dener 
31513b46278SAlp Dener   if (is_lmvm) {
31613b46278SAlp Dener     lmP = (TAO_LMVM *)tao->data;
31713b46278SAlp Dener     ierr = PetscObjectReference((PetscObject)H0);CHKERRQ(ierr);
31813b46278SAlp Dener     lmP->H0 = H0;
31913b46278SAlp Dener   } else if (is_blmvm) {
32013b46278SAlp Dener     blmP = (TAO_BLMVM *)tao->data;
32113b46278SAlp Dener     ierr = PetscObjectReference((PetscObject)H0);CHKERRQ(ierr);
32213b46278SAlp Dener     blmP->H0 = H0;
32313b46278SAlp Dener   } else SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "This routine applies to TAO_LMVM and TAO_BLMVM.");
32413b46278SAlp Dener   PetscFunctionReturn(0);
32513b46278SAlp Dener }
32613b46278SAlp Dener 
32713b46278SAlp Dener PETSC_EXTERN PetscErrorCode TaoLMVMGetH0(Tao tao, Mat *H0)
32813b46278SAlp Dener {
32913b46278SAlp Dener   TAO_LMVM       *lmP;
33013b46278SAlp Dener   TAO_BLMVM      *blmP;
33113b46278SAlp Dener   const TaoType  type;
33213b46278SAlp Dener   PetscBool      is_lmvm, is_blmvm;
33313b46278SAlp Dener   Mat            M;
33413b46278SAlp Dener 
33513b46278SAlp Dener   PetscErrorCode ierr;
33613b46278SAlp Dener 
33713b46278SAlp Dener   ierr = TaoGetType(tao, &type);CHKERRQ(ierr);
33813b46278SAlp Dener   ierr = PetscStrcmp(type, TAOLMVM,  &is_lmvm);CHKERRQ(ierr);
33913b46278SAlp Dener   ierr = PetscStrcmp(type, TAOBLMVM, &is_blmvm);CHKERRQ(ierr);
34013b46278SAlp Dener 
34113b46278SAlp Dener   if (is_lmvm) {
34213b46278SAlp Dener     lmP = (TAO_LMVM *)tao->data;
34313b46278SAlp Dener     M = lmP->M;
34413b46278SAlp Dener   } else if (is_blmvm) {
34513b46278SAlp Dener     blmP = (TAO_BLMVM *)tao->data;
34613b46278SAlp Dener     M = blmP->M;
34713b46278SAlp Dener   } else SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "This routine applies to TAO_LMVM and TAO_BLMVM.");
34813b46278SAlp Dener   ierr = MatLMVMGetJ0(M, H0);CHKERRQ(ierr);
34913b46278SAlp Dener   PetscFunctionReturn(0);
35013b46278SAlp Dener }
35113b46278SAlp Dener 
35213b46278SAlp Dener PETSC_EXTERN PetscErrorCode TaoLMVMGetH0KSP(Tao tao, KSP *ksp)
35313b46278SAlp Dener {
35413b46278SAlp Dener   TAO_LMVM       *lmP;
35513b46278SAlp Dener   TAO_BLMVM      *blmP;
35613b46278SAlp Dener   const TaoType  type;
35713b46278SAlp Dener   PetscBool      is_lmvm, is_blmvm;
35813b46278SAlp Dener   Mat            M;
35913b46278SAlp Dener   PetscErrorCode ierr;
36013b46278SAlp Dener 
36113b46278SAlp Dener   ierr = TaoGetType(tao, &type);CHKERRQ(ierr);
36213b46278SAlp Dener   ierr = PetscStrcmp(type, TAOLMVM,  &is_lmvm);CHKERRQ(ierr);
36313b46278SAlp Dener   ierr = PetscStrcmp(type, TAOBLMVM, &is_blmvm);CHKERRQ(ierr);
36413b46278SAlp Dener 
36513b46278SAlp Dener   if (is_lmvm) {
36613b46278SAlp Dener     lmP = (TAO_LMVM *)tao->data;
36713b46278SAlp Dener     M = lmP->M;
36813b46278SAlp Dener   } else if (is_blmvm) {
36913b46278SAlp Dener     blmP = (TAO_BLMVM *)tao->data;
37013b46278SAlp Dener     M = blmP->M;
37113b46278SAlp Dener   } else SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "This routine applies to TAO_LMVM and TAO_BLMVM.");
37213b46278SAlp Dener   ierr = MatLMVMGetJ0KSP(M, ksp);CHKERRQ(ierr);
37313b46278SAlp Dener   PetscFunctionReturn(0);
37413b46278SAlp Dener }