xref: /petsc/src/tao/unconstrained/impls/lmvm/lmvm.c (revision d5ae23803a94ca2b9c66785d81449705f0cc1e9e)
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;
48cd929ea3SAlp Dener     }
49a7e14dcfSSatish Balay     ierr = MatLMVMUpdate(lmP->M,tao->solution,tao->gradient);CHKERRQ(ierr);
50cd929ea3SAlp Dener     ierr = MatSolve(lmP->M, tao->gradient, lmP->D);CHKERRQ(ierr);
51cd929ea3SAlp Dener     ierr = MatLMVMGetUpdateCount(lmP->M, &nupdates); CHKERRQ(ierr);
52cd929ea3SAlp Dener     if (nupdates > 0) stepType = LMVM_STEP_BFGS;
53a7e14dcfSSatish Balay 
54a7e14dcfSSatish Balay     /*  Check for success (descent direction) */
55a7e14dcfSSatish Balay     ierr = VecDot(lmP->D, tao->gradient, &gdx);CHKERRQ(ierr);
56a7e14dcfSSatish Balay     if ((gdx <= 0.0) || PetscIsInfOrNanReal(gdx)) {
57a7e14dcfSSatish Balay       /* Step is not descent or direction produced not a number
58a7e14dcfSSatish Balay          We can assert bfgsUpdates > 1 in this case because
59a7e14dcfSSatish Balay          the first solve produces the scaled gradient direction,
60a7e14dcfSSatish Balay          which is guaranteed to be descent
61a7e14dcfSSatish Balay 
62a7e14dcfSSatish Balay          Use steepest descent direction (scaled)
63a7e14dcfSSatish Balay       */
64a7e14dcfSSatish Balay 
65cd929ea3SAlp Dener       ierr = MatLMVMReset(lmP->M, PETSC_FALSE);CHKERRQ(ierr);
660ad3a497SAlp Dener       ierr = MatLMVMClearJ0(lmP->M);CHKERRQ(ierr);
67a7e14dcfSSatish Balay       ierr = MatLMVMUpdate(lmP->M, tao->solution, tao->gradient);CHKERRQ(ierr);
68cd929ea3SAlp Dener       ierr = MatSolve(lmP->M,tao->gradient, lmP->D);CHKERRQ(ierr);
69a7e14dcfSSatish Balay 
70a7e14dcfSSatish Balay       /* On a reset, the direction cannot be not a number; it is a
71a7e14dcfSSatish Balay          scaled gradient step.  No need to check for this condition. */
72cd929ea3SAlp Dener       stepType = LMVM_STEP_GRAD;
73a7e14dcfSSatish Balay     }
74a7e14dcfSSatish Balay     ierr = VecScale(lmP->D, -1.0);CHKERRQ(ierr);
75a7e14dcfSSatish Balay 
76a7e14dcfSSatish Balay     /*  Perform the linesearch */
77a7e14dcfSSatish Balay     fold = f;
78a7e14dcfSSatish Balay     ierr = VecCopy(tao->solution, lmP->Xold);CHKERRQ(ierr);
79a7e14dcfSSatish Balay     ierr = VecCopy(tao->gradient, lmP->Gold);CHKERRQ(ierr);
80a7e14dcfSSatish Balay 
81a7e14dcfSSatish Balay     ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &f, tao->gradient, lmP->D, &step,&ls_status);CHKERRQ(ierr);
82a7e14dcfSSatish Balay     ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
83a7e14dcfSSatish Balay 
84cd929ea3SAlp Dener     if (ls_status != TAOLINESEARCH_SUCCESS && ls_status != TAOLINESEARCH_SUCCESS_USER && (stepType != LMVM_STEP_GRAD)) {
85a7e14dcfSSatish Balay       /*  Reset factors and use scaled gradient step */
86a7e14dcfSSatish Balay       f = fold;
87a7e14dcfSSatish Balay       ierr = VecCopy(lmP->Xold, tao->solution);CHKERRQ(ierr);
88a7e14dcfSSatish Balay       ierr = VecCopy(lmP->Gold, tao->gradient);CHKERRQ(ierr);
89a7e14dcfSSatish Balay 
90a7e14dcfSSatish Balay       /*  Failed to obtain acceptable iterate with BFGS step */
91a7e14dcfSSatish Balay       /*  Attempt to use the scaled gradient direction */
92a7e14dcfSSatish Balay 
93cd929ea3SAlp Dener       ierr = MatLMVMReset(lmP->M, PETSC_FALSE);CHKERRQ(ierr);
940ad3a497SAlp Dener       ierr = MatLMVMClearJ0(lmP->M);CHKERRQ(ierr);
95a7e14dcfSSatish Balay       ierr = MatLMVMUpdate(lmP->M, tao->solution, tao->gradient);CHKERRQ(ierr);
96cd929ea3SAlp Dener       ierr = MatSolve(lmP->M, tao->solution, tao->gradient);CHKERRQ(ierr);
97a7e14dcfSSatish Balay 
98a7e14dcfSSatish Balay       /* On a reset, the direction cannot be not a number; it is a
99a7e14dcfSSatish Balay           scaled gradient step.  No need to check for this condition. */
100cd929ea3SAlp Dener       stepType = LMVM_STEP_GRAD;
101a7e14dcfSSatish Balay       ierr = VecScale(lmP->D, -1.0);CHKERRQ(ierr);
102a7e14dcfSSatish Balay 
103a7e14dcfSSatish Balay       /*  Perform the linesearch */
104a7e14dcfSSatish Balay       ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &f, tao->gradient, lmP->D, &step, &ls_status);CHKERRQ(ierr);
105a7e14dcfSSatish Balay       ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
106a7e14dcfSSatish Balay     }
107a7e14dcfSSatish Balay 
10887f595a5SBarry Smith     if (ls_status != TAOLINESEARCH_SUCCESS && ls_status != TAOLINESEARCH_SUCCESS_USER) {
109a7e14dcfSSatish Balay       /*  Failed to find an improving point */
110a7e14dcfSSatish Balay       f = fold;
111a7e14dcfSSatish Balay       ierr = VecCopy(lmP->Xold, tao->solution);CHKERRQ(ierr);
112a7e14dcfSSatish Balay       ierr = VecCopy(lmP->Gold, tao->gradient);CHKERRQ(ierr);
113a7e14dcfSSatish Balay       step = 0.0;
114a7e14dcfSSatish Balay       tao->reason = TAO_DIVERGED_LS_FAILURE;
115cd929ea3SAlp Dener     } else {
116cd929ea3SAlp Dener       /* LS found valid step, so tally up step type */
117cd929ea3SAlp Dener       switch (stepType) {
118cd929ea3SAlp Dener       case LMVM_STEP_BFGS:
119cd929ea3SAlp Dener         ++lmP->bfgs;
120cd929ea3SAlp Dener         break;
121cd929ea3SAlp Dener       case LMVM_STEP_GRAD:
122cd929ea3SAlp Dener         ++lmP->grad;
123cd929ea3SAlp Dener         break;
124cd929ea3SAlp Dener       default:
125cd929ea3SAlp Dener         break;
126cd929ea3SAlp Dener       }
127cd929ea3SAlp Dener       /*  Compute new gradient norm */
128cd929ea3SAlp Dener       ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&gnorm);CHKERRQ(ierr);
129a7e14dcfSSatish Balay     }
130a9603a14SPatrick Farrell 
131cd929ea3SAlp Dener     /* Check convergence */
1328931d482SJason Sarich     tao->niter++;
1333ecd9318SAlp Dener     ierr = TaoLogConvergenceHistory(tao,f,gnorm,0.0,tao->ksp_its);CHKERRQ(ierr);
1343ecd9318SAlp Dener     ierr = TaoMonitor(tao,tao->niter,f,gnorm,0.0,step);CHKERRQ(ierr);
1353ecd9318SAlp Dener     ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
136a7e14dcfSSatish Balay   }
137a7e14dcfSSatish Balay   PetscFunctionReturn(0);
138a7e14dcfSSatish Balay }
13987f595a5SBarry Smith 
140441846f8SBarry Smith static PetscErrorCode TaoSetUp_LMVM(Tao tao)
141a7e14dcfSSatish Balay {
142a7e14dcfSSatish Balay   TAO_LMVM       *lmP = (TAO_LMVM *)tao->data;
143a7e14dcfSSatish Balay   PetscInt       n,N;
144a7e14dcfSSatish Balay   PetscErrorCode ierr;
145*d5ae2380SAlp Dener   PetscBool      is_spd;
146a7e14dcfSSatish Balay 
147a7e14dcfSSatish Balay   PetscFunctionBegin;
148a7e14dcfSSatish Balay   /* Existence of tao->solution checked in TaoSetUp() */
149a7e14dcfSSatish Balay   if (!tao->gradient) {ierr = VecDuplicate(tao->solution,&tao->gradient);CHKERRQ(ierr);  }
150a7e14dcfSSatish Balay   if (!tao->stepdirection) {ierr = VecDuplicate(tao->solution,&tao->stepdirection);CHKERRQ(ierr);  }
151a7e14dcfSSatish Balay   if (!lmP->D) {ierr = VecDuplicate(tao->solution,&lmP->D);CHKERRQ(ierr);  }
152a7e14dcfSSatish Balay   if (!lmP->Xold) {ierr = VecDuplicate(tao->solution,&lmP->Xold);CHKERRQ(ierr);  }
153a7e14dcfSSatish Balay   if (!lmP->Gold) {ierr = VecDuplicate(tao->solution,&lmP->Gold);CHKERRQ(ierr);  }
154a7e14dcfSSatish Balay 
155a7e14dcfSSatish Balay   /*  Create matrix for the limited memory approximation */
156a7e14dcfSSatish Balay   ierr = VecGetLocalSize(tao->solution,&n);CHKERRQ(ierr);
157a7e14dcfSSatish Balay   ierr = VecGetSize(tao->solution,&N);CHKERRQ(ierr);
158cd929ea3SAlp Dener   ierr = MatSetSizes(lmP->M, n, n, N, N);CHKERRQ(ierr);
159cd929ea3SAlp Dener   ierr = MatLMVMAllocate(lmP->M,tao->solution,tao->gradient);CHKERRQ(ierr);
1600ad3a497SAlp Dener   ierr = MatGetOption(lmP->M, MAT_SPD, &is_spd);CHKERRQ(ierr);
1610ad3a497SAlp Dener   if (!is_spd) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "LMVM matrix is not symmetric positive-definite.");
162a9603a14SPatrick Farrell 
163a9603a14SPatrick Farrell   /* If the user has set a matrix to solve as the initial H0, set the options prefix here, and set up the KSP */
164a9603a14SPatrick Farrell   if (lmP->H0) {
165cd929ea3SAlp Dener     ierr = MatLMVMSetJ0(lmP->M, lmP->H0);CHKERRQ(ierr);
166a9603a14SPatrick Farrell   }
167a9603a14SPatrick Farrell 
168a7e14dcfSSatish Balay   PetscFunctionReturn(0);
169a7e14dcfSSatish Balay }
170a7e14dcfSSatish Balay 
171a7e14dcfSSatish Balay /* ---------------------------------------------------------- */
172441846f8SBarry Smith static PetscErrorCode TaoDestroy_LMVM(Tao tao)
173a7e14dcfSSatish Balay {
174a7e14dcfSSatish Balay   TAO_LMVM       *lmP = (TAO_LMVM *)tao->data;
175a7e14dcfSSatish Balay   PetscErrorCode ierr;
176a7e14dcfSSatish Balay 
177a7e14dcfSSatish Balay   PetscFunctionBegin;
178a7e14dcfSSatish Balay   if (tao->setupcalled) {
179a7e14dcfSSatish Balay     ierr = VecDestroy(&lmP->Xold);CHKERRQ(ierr);
180a7e14dcfSSatish Balay     ierr = VecDestroy(&lmP->Gold);CHKERRQ(ierr);
181a7e14dcfSSatish Balay     ierr = VecDestroy(&lmP->D);CHKERRQ(ierr);
182a7e14dcfSSatish Balay   }
183cd929ea3SAlp Dener   ierr = MatDestroy(&lmP->M);CHKERRQ(ierr);
184a9603a14SPatrick Farrell   if (lmP->H0) {
185a9603a14SPatrick Farrell     ierr = PetscObjectDereference((PetscObject)lmP->H0);CHKERRQ(ierr);
186a9603a14SPatrick Farrell   }
187a7e14dcfSSatish Balay   ierr = PetscFree(tao->data);CHKERRQ(ierr);
188a9603a14SPatrick Farrell 
189a7e14dcfSSatish Balay   PetscFunctionReturn(0);
190a7e14dcfSSatish Balay }
191a7e14dcfSSatish Balay 
192a7e14dcfSSatish Balay /*------------------------------------------------------------*/
1934416b707SBarry Smith static PetscErrorCode TaoSetFromOptions_LMVM(PetscOptionItems *PetscOptionsObject,Tao tao)
194a7e14dcfSSatish Balay {
195cd929ea3SAlp Dener   TAO_LMVM       *lm = (TAO_LMVM *)tao->data;
196a7e14dcfSSatish Balay   PetscErrorCode ierr;
197a7e14dcfSSatish Balay 
198a7e14dcfSSatish Balay   PetscFunctionBegin;
1991a1499c8SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"Limited-memory variable-metric method for unconstrained optimization");CHKERRQ(ierr);
200cd929ea3SAlp Dener   ierr = PetscOptionsBool("-tao_lmvm_recycle","enable recycling of the BFGS matrix between subsequent TaoSolve() calls","",lm->recycle,&lm->recycle,NULL);CHKERRQ(ierr);
201114d2d62SAlp Dener   ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr);
202cd929ea3SAlp Dener   ierr = MatSetFromOptions(lm->M);CHKERRQ(ierr);
203288b7216SAlp Dener   ierr = PetscOptionsTail();CHKERRQ(ierr);
204a7e14dcfSSatish Balay   PetscFunctionReturn(0);
205a7e14dcfSSatish Balay }
206a7e14dcfSSatish Balay 
207a7e14dcfSSatish Balay /*------------------------------------------------------------*/
208441846f8SBarry Smith static PetscErrorCode TaoView_LMVM(Tao tao, PetscViewer viewer)
209a7e14dcfSSatish Balay {
210a7e14dcfSSatish Balay   TAO_LMVM       *lm = (TAO_LMVM *)tao->data;
211cd929ea3SAlp Dener   PetscBool      isascii;
2124d6623b4SAlp Dener   PetscInt       recycled_its;
213a7e14dcfSSatish Balay   PetscErrorCode ierr;
214a7e14dcfSSatish Balay 
215a7e14dcfSSatish Balay   PetscFunctionBegin;
216a7e14dcfSSatish Balay   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr);
217a7e14dcfSSatish Balay   if (isascii) {
218a7e14dcfSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer, "  Gradient steps: %D\n", lm->grad);CHKERRQ(ierr);
219cd929ea3SAlp Dener     if (lm->recycle) {
220288b7216SAlp Dener       ierr = PetscViewerASCIIPrintf(viewer, "  Recycle: on\n");CHKERRQ(ierr);
221cd929ea3SAlp Dener       recycled_its = lm->bfgs + lm->grad;
2224d6623b4SAlp Dener       ierr = PetscViewerASCIIPrintf(viewer, "  Total recycled iterations: %D\n", recycled_its);CHKERRQ(ierr);
223a0bfee83SAlp Dener     }
224a7e14dcfSSatish Balay   }
225a7e14dcfSSatish Balay   PetscFunctionReturn(0);
226a7e14dcfSSatish Balay }
227a7e14dcfSSatish Balay 
228a7e14dcfSSatish Balay /* ---------------------------------------------------------- */
229a7e14dcfSSatish Balay 
2304aa34175SJason Sarich /*MC
2314aa34175SJason Sarich   TAOLMVM - Limited Memory Variable Metric method is a quasi-Newton
2324aa34175SJason Sarich   optimization solver for unconstrained minimization. It solves
2334aa34175SJason Sarich   the Newton step
2344aa34175SJason Sarich           Hkdk = - gk
2354aa34175SJason Sarich 
2364aa34175SJason Sarich   using an approximation Bk in place of Hk, where Bk is composed using
2374aa34175SJason Sarich   the BFGS update formula. A More-Thuente line search is then used
2384aa34175SJason Sarich   to computed the steplength in the dk direction
2390ad3a497SAlp Dener 
2404aa34175SJason Sarich   Options Database Keys:
241cd929ea3SAlp Dener .   -tao_lmvm_recycle - enable recycling LMVM updates between TaoSolve() calls
2420ad3a497SAlp Dener .   -tao_lmvm_no_scale - (developer) disables diagonal Broyden scaling on the LMVM approximation
2434aa34175SJason Sarich 
2441eb8069cSJason Sarich   Level: beginner
2454aa34175SJason Sarich M*/
2464aa34175SJason Sarich 
247728e0ed0SBarry Smith PETSC_EXTERN PetscErrorCode TaoCreate_LMVM(Tao tao)
248a7e14dcfSSatish Balay {
249a7e14dcfSSatish Balay   TAO_LMVM       *lmP;
2508caf6e8cSBarry Smith   const char     *morethuente_type = TAOLINESEARCHMT;
251a7e14dcfSSatish Balay   PetscErrorCode ierr;
252a7e14dcfSSatish Balay 
253a7e14dcfSSatish Balay   PetscFunctionBegin;
254a7e14dcfSSatish Balay   tao->ops->setup = TaoSetUp_LMVM;
255a7e14dcfSSatish Balay   tao->ops->solve = TaoSolve_LMVM;
256a7e14dcfSSatish Balay   tao->ops->view = TaoView_LMVM;
257a7e14dcfSSatish Balay   tao->ops->setfromoptions = TaoSetFromOptions_LMVM;
258a7e14dcfSSatish Balay   tao->ops->destroy = TaoDestroy_LMVM;
259a7e14dcfSSatish Balay 
2603c9e27cfSGeoffrey Irving   ierr = PetscNewLog(tao,&lmP);CHKERRQ(ierr);
261a7e14dcfSSatish Balay   lmP->D = 0;
262a7e14dcfSSatish Balay   lmP->M = 0;
263a7e14dcfSSatish Balay   lmP->Xold = 0;
264a7e14dcfSSatish Balay   lmP->Gold = 0;
265a9603a14SPatrick Farrell   lmP->H0   = NULL;
266cd929ea3SAlp Dener   lmP->recycle = PETSC_FALSE;
267a7e14dcfSSatish Balay 
268a7e14dcfSSatish Balay   tao->data = (void*)lmP;
2696552cf8aSJason Sarich   /* Override default settings (unless already changed) */
2706552cf8aSJason Sarich   if (!tao->max_it_changed) tao->max_it = 2000;
2716552cf8aSJason Sarich   if (!tao->max_funcs_changed) tao->max_funcs = 4000;
272a7e14dcfSSatish Balay 
273a7e14dcfSSatish Balay   ierr = TaoLineSearchCreate(((PetscObject)tao)->comm,&tao->linesearch);CHKERRQ(ierr);
27463b15415SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)tao->linesearch, (PetscObject)tao, 1);CHKERRQ(ierr);
275a7e14dcfSSatish Balay   ierr = TaoLineSearchSetType(tao->linesearch,morethuente_type);CHKERRQ(ierr);
276441846f8SBarry Smith   ierr = TaoLineSearchUseTaoRoutines(tao->linesearch,tao);CHKERRQ(ierr);
2775d527766SPatrick Farrell   ierr = TaoLineSearchSetOptionsPrefix(tao->linesearch,tao->hdr.prefix);CHKERRQ(ierr);
278cd929ea3SAlp Dener 
279cd929ea3SAlp Dener   ierr = KSPInitializePackage();CHKERRQ(ierr);
280cd929ea3SAlp Dener   ierr = MatCreate(((PetscObject)tao)->comm, &lmP->M);CHKERRQ(ierr);
281cd929ea3SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)lmP->M, (PetscObject)tao, 1);CHKERRQ(ierr);
28278e4361aSAlp Dener   ierr = MatSetType(lmP->M, MATLMVMBFGS);CHKERRQ(ierr);
283cd929ea3SAlp Dener   ierr = MatSetOptionsPrefix(lmP->M, "tao_lmvm_");CHKERRQ(ierr);
284a7e14dcfSSatish Balay   PetscFunctionReturn(0);
285a7e14dcfSSatish Balay }
28613b46278SAlp Dener 
28713b46278SAlp Dener PETSC_EXTERN PetscErrorCode TaoLMVMSetH0(Tao tao, Mat H0)
28813b46278SAlp Dener {
28913b46278SAlp Dener   TAO_LMVM       *lmP;
29013b46278SAlp Dener   TAO_BLMVM      *blmP;
2914f4fdda4SAlp Dener   TaoType        type;
29213b46278SAlp Dener   PetscBool      is_lmvm, is_blmvm;
29313b46278SAlp Dener   PetscErrorCode ierr;
29413b46278SAlp Dener 
29513b46278SAlp Dener   ierr = TaoGetType(tao, &type);CHKERRQ(ierr);
29613b46278SAlp Dener   ierr = PetscStrcmp(type, TAOLMVM,  &is_lmvm);CHKERRQ(ierr);
29713b46278SAlp Dener   ierr = PetscStrcmp(type, TAOBLMVM, &is_blmvm);CHKERRQ(ierr);
29813b46278SAlp Dener 
29913b46278SAlp Dener   if (is_lmvm) {
30013b46278SAlp Dener     lmP = (TAO_LMVM *)tao->data;
30113b46278SAlp Dener     ierr = PetscObjectReference((PetscObject)H0);CHKERRQ(ierr);
30213b46278SAlp Dener     lmP->H0 = H0;
30313b46278SAlp Dener   } else if (is_blmvm) {
30413b46278SAlp Dener     blmP = (TAO_BLMVM *)tao->data;
30513b46278SAlp Dener     ierr = PetscObjectReference((PetscObject)H0);CHKERRQ(ierr);
30613b46278SAlp Dener     blmP->H0 = H0;
30713b46278SAlp Dener   } else SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "This routine applies to TAO_LMVM and TAO_BLMVM.");
30813b46278SAlp Dener   PetscFunctionReturn(0);
30913b46278SAlp Dener }
31013b46278SAlp Dener 
31113b46278SAlp Dener PETSC_EXTERN PetscErrorCode TaoLMVMGetH0(Tao tao, Mat *H0)
31213b46278SAlp Dener {
31313b46278SAlp Dener   TAO_LMVM       *lmP;
31413b46278SAlp Dener   TAO_BLMVM      *blmP;
3154f4fdda4SAlp Dener   TaoType        type;
31613b46278SAlp Dener   PetscBool      is_lmvm, is_blmvm;
31713b46278SAlp Dener   Mat            M;
31813b46278SAlp Dener 
31913b46278SAlp Dener   PetscErrorCode ierr;
32013b46278SAlp Dener 
32113b46278SAlp Dener   ierr = TaoGetType(tao, &type);CHKERRQ(ierr);
32213b46278SAlp Dener   ierr = PetscStrcmp(type, TAOLMVM,  &is_lmvm);CHKERRQ(ierr);
32313b46278SAlp Dener   ierr = PetscStrcmp(type, TAOBLMVM, &is_blmvm);CHKERRQ(ierr);
32413b46278SAlp Dener 
32513b46278SAlp Dener   if (is_lmvm) {
32613b46278SAlp Dener     lmP = (TAO_LMVM *)tao->data;
32713b46278SAlp Dener     M = lmP->M;
32813b46278SAlp Dener   } else if (is_blmvm) {
32913b46278SAlp Dener     blmP = (TAO_BLMVM *)tao->data;
33013b46278SAlp Dener     M = blmP->M;
33113b46278SAlp Dener   } else SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "This routine applies to TAO_LMVM and TAO_BLMVM.");
33213b46278SAlp Dener   ierr = MatLMVMGetJ0(M, H0);CHKERRQ(ierr);
33313b46278SAlp Dener   PetscFunctionReturn(0);
33413b46278SAlp Dener }
33513b46278SAlp Dener 
33613b46278SAlp Dener PETSC_EXTERN PetscErrorCode TaoLMVMGetH0KSP(Tao tao, KSP *ksp)
33713b46278SAlp Dener {
33813b46278SAlp Dener   TAO_LMVM       *lmP;
33913b46278SAlp Dener   TAO_BLMVM      *blmP;
3404f4fdda4SAlp Dener   TaoType        type;
34113b46278SAlp Dener   PetscBool      is_lmvm, is_blmvm;
34213b46278SAlp Dener   Mat            M;
34313b46278SAlp Dener   PetscErrorCode ierr;
34413b46278SAlp Dener 
34513b46278SAlp Dener   ierr = TaoGetType(tao, &type);CHKERRQ(ierr);
34613b46278SAlp Dener   ierr = PetscStrcmp(type, TAOLMVM,  &is_lmvm);CHKERRQ(ierr);
34713b46278SAlp Dener   ierr = PetscStrcmp(type, TAOBLMVM, &is_blmvm);CHKERRQ(ierr);
34813b46278SAlp Dener 
34913b46278SAlp Dener   if (is_lmvm) {
35013b46278SAlp Dener     lmP = (TAO_LMVM *)tao->data;
35113b46278SAlp Dener     M = lmP->M;
35213b46278SAlp Dener   } else if (is_blmvm) {
35313b46278SAlp Dener     blmP = (TAO_BLMVM *)tao->data;
35413b46278SAlp Dener     M = blmP->M;
35513b46278SAlp Dener   } else SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "This routine applies to TAO_LMVM and TAO_BLMVM.");
35613b46278SAlp Dener   ierr = MatLMVMGetJ0KSP(M, ksp);CHKERRQ(ierr);
35713b46278SAlp Dener   PetscFunctionReturn(0);
35813b46278SAlp Dener }