xref: /petsc/src/tao/unconstrained/impls/lmvm/lmvm.c (revision 13b462789fddc29992ec6ad2a1d523c642b9dca7)
1ba92ff59SBarry Smith #include <petsctaolinesearch.h>
2aaa7dc30SBarry Smith #include <../src/tao/unconstrained/impls/lmvm/lmvm.h>
3*13b46278SAlp 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 
65b2d8c577SAlp Dener       ierr = MatLMVMResetJ0(lmP->M);CHKERRQ(ierr);
66cd929ea3SAlp Dener       ierr = MatLMVMReset(lmP->M, PETSC_FALSE);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 
93b2d8c577SAlp Dener       ierr = MatLMVMResetJ0(lmP->M);CHKERRQ(ierr);
94cd929ea3SAlp Dener       ierr = MatLMVMReset(lmP->M, PETSC_FALSE);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;
145a7e14dcfSSatish Balay 
146a7e14dcfSSatish Balay   PetscFunctionBegin;
147a7e14dcfSSatish Balay   /* Existence of tao->solution checked in TaoSetUp() */
148a7e14dcfSSatish Balay   if (!tao->gradient) {ierr = VecDuplicate(tao->solution,&tao->gradient);CHKERRQ(ierr);  }
149a7e14dcfSSatish Balay   if (!tao->stepdirection) {ierr = VecDuplicate(tao->solution,&tao->stepdirection);CHKERRQ(ierr);  }
150a7e14dcfSSatish Balay   if (!lmP->D) {ierr = VecDuplicate(tao->solution,&lmP->D);CHKERRQ(ierr);  }
151a7e14dcfSSatish Balay   if (!lmP->Xold) {ierr = VecDuplicate(tao->solution,&lmP->Xold);CHKERRQ(ierr);  }
152a7e14dcfSSatish Balay   if (!lmP->Gold) {ierr = VecDuplicate(tao->solution,&lmP->Gold);CHKERRQ(ierr);  }
153a7e14dcfSSatish Balay 
154a7e14dcfSSatish Balay   /*  Create matrix for the limited memory approximation */
155a7e14dcfSSatish Balay   ierr = VecGetLocalSize(tao->solution,&n);CHKERRQ(ierr);
156a7e14dcfSSatish Balay   ierr = VecGetSize(tao->solution,&N);CHKERRQ(ierr);
157cd929ea3SAlp Dener   ierr = MatSetSizes(lmP->M, n, n, N, N);CHKERRQ(ierr);
158cd929ea3SAlp Dener   ierr = MatLMVMAllocate(lmP->M,tao->solution,tao->gradient);CHKERRQ(ierr);
159a9603a14SPatrick Farrell 
160a9603a14SPatrick Farrell   /* If the user has set a matrix to solve as the initial H0, set the options prefix here, and set up the KSP */
161a9603a14SPatrick Farrell   if (lmP->H0) {
162cd929ea3SAlp Dener     ierr = MatLMVMSetJ0(lmP->M, lmP->H0);CHKERRQ(ierr);
163a9603a14SPatrick Farrell   }
164a9603a14SPatrick Farrell 
165a7e14dcfSSatish Balay   PetscFunctionReturn(0);
166a7e14dcfSSatish Balay }
167a7e14dcfSSatish Balay 
168a7e14dcfSSatish Balay /* ---------------------------------------------------------- */
169441846f8SBarry Smith static PetscErrorCode TaoDestroy_LMVM(Tao tao)
170a7e14dcfSSatish Balay {
171a7e14dcfSSatish Balay   TAO_LMVM       *lmP = (TAO_LMVM *)tao->data;
172a7e14dcfSSatish Balay   PetscErrorCode ierr;
173a7e14dcfSSatish Balay 
174a7e14dcfSSatish Balay   PetscFunctionBegin;
175a7e14dcfSSatish Balay   if (tao->setupcalled) {
176a7e14dcfSSatish Balay     ierr = VecDestroy(&lmP->Xold);CHKERRQ(ierr);
177a7e14dcfSSatish Balay     ierr = VecDestroy(&lmP->Gold);CHKERRQ(ierr);
178a7e14dcfSSatish Balay     ierr = VecDestroy(&lmP->D);CHKERRQ(ierr);
179a7e14dcfSSatish Balay   }
180cd929ea3SAlp Dener   ierr = MatDestroy(&lmP->M);CHKERRQ(ierr);
181a9603a14SPatrick Farrell   if (lmP->H0) {
182a9603a14SPatrick Farrell     ierr = PetscObjectDereference((PetscObject)lmP->H0);CHKERRQ(ierr);
183a9603a14SPatrick Farrell   }
184a7e14dcfSSatish Balay   ierr = PetscFree(tao->data);CHKERRQ(ierr);
185a9603a14SPatrick Farrell 
186a7e14dcfSSatish Balay   PetscFunctionReturn(0);
187a7e14dcfSSatish Balay }
188a7e14dcfSSatish Balay 
189a7e14dcfSSatish Balay /*------------------------------------------------------------*/
1904416b707SBarry Smith static PetscErrorCode TaoSetFromOptions_LMVM(PetscOptionItems *PetscOptionsObject,Tao tao)
191a7e14dcfSSatish Balay {
192cd929ea3SAlp Dener   TAO_LMVM       *lm = (TAO_LMVM *)tao->data;
193a7e14dcfSSatish Balay   PetscErrorCode ierr;
194a7e14dcfSSatish Balay 
195a7e14dcfSSatish Balay   PetscFunctionBegin;
1961a1499c8SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"Limited-memory variable-metric method for unconstrained optimization");CHKERRQ(ierr);
197cd929ea3SAlp Dener   ierr = PetscOptionsBool("-tao_lmvm_recycle","enable recycling of the BFGS matrix between subsequent TaoSolve() calls","",lm->recycle,&lm->recycle,NULL);CHKERRQ(ierr);
198114d2d62SAlp Dener   ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr);
199cd929ea3SAlp Dener   ierr = MatSetFromOptions(lm->M);CHKERRQ(ierr);
200288b7216SAlp Dener   ierr = PetscOptionsTail();CHKERRQ(ierr);
201a7e14dcfSSatish Balay   PetscFunctionReturn(0);
202a7e14dcfSSatish Balay }
203a7e14dcfSSatish Balay 
204a7e14dcfSSatish Balay /*------------------------------------------------------------*/
205441846f8SBarry Smith static PetscErrorCode TaoView_LMVM(Tao tao, PetscViewer viewer)
206a7e14dcfSSatish Balay {
207a7e14dcfSSatish Balay   TAO_LMVM       *lm = (TAO_LMVM *)tao->data;
208cd929ea3SAlp Dener   PetscBool      isascii;
2094d6623b4SAlp Dener   PetscInt       recycled_its;
210a7e14dcfSSatish Balay   PetscErrorCode ierr;
211a7e14dcfSSatish Balay 
212a7e14dcfSSatish Balay   PetscFunctionBegin;
213a7e14dcfSSatish Balay   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr);
214a7e14dcfSSatish Balay   if (isascii) {
215a7e14dcfSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer, "  Gradient steps: %D\n", lm->grad);CHKERRQ(ierr);
216cd929ea3SAlp Dener     if (lm->recycle) {
217288b7216SAlp Dener       ierr = PetscViewerASCIIPrintf(viewer, "  Recycle: on\n");CHKERRQ(ierr);
218cd929ea3SAlp Dener       recycled_its = lm->bfgs + lm->grad;
2194d6623b4SAlp Dener       ierr = PetscViewerASCIIPrintf(viewer, "  Total recycled iterations: %D\n", recycled_its);CHKERRQ(ierr);
220a0bfee83SAlp Dener     }
221a7e14dcfSSatish Balay   }
222a7e14dcfSSatish Balay   PetscFunctionReturn(0);
223a7e14dcfSSatish Balay }
224a7e14dcfSSatish Balay 
225a7e14dcfSSatish Balay /* ---------------------------------------------------------- */
226a7e14dcfSSatish Balay 
2274aa34175SJason Sarich /*MC
2284aa34175SJason Sarich      TAOLMVM - Limited Memory Variable Metric method is a quasi-Newton
2294aa34175SJason Sarich      optimization solver for unconstrained minimization. It solves
2304aa34175SJason Sarich      the Newton step
2314aa34175SJason Sarich               Hkdk = - gk
2324aa34175SJason Sarich 
2334aa34175SJason Sarich      using an approximation Bk in place of Hk, where Bk is composed using
2344aa34175SJason Sarich      the BFGS update formula. A More-Thuente line search is then used
2354aa34175SJason Sarich      to computed the steplength in the dk direction
2364aa34175SJason Sarich   Options Database Keys:
237cd929ea3SAlp Dener .     -tao_lmvm_recycle - enable recycling LMVM updates between TaoSolve() calls
2384aa34175SJason Sarich 
2391eb8069cSJason Sarich   Level: beginner
2404aa34175SJason Sarich M*/
2414aa34175SJason Sarich 
242728e0ed0SBarry Smith PETSC_EXTERN PetscErrorCode TaoCreate_LMVM(Tao tao)
243a7e14dcfSSatish Balay {
244a7e14dcfSSatish Balay   TAO_LMVM       *lmP;
2458caf6e8cSBarry Smith   const char     *morethuente_type = TAOLINESEARCHMT;
246a7e14dcfSSatish Balay   PetscErrorCode ierr;
247a7e14dcfSSatish Balay 
248a7e14dcfSSatish Balay   PetscFunctionBegin;
249a7e14dcfSSatish Balay   tao->ops->setup = TaoSetUp_LMVM;
250a7e14dcfSSatish Balay   tao->ops->solve = TaoSolve_LMVM;
251a7e14dcfSSatish Balay   tao->ops->view = TaoView_LMVM;
252a7e14dcfSSatish Balay   tao->ops->setfromoptions = TaoSetFromOptions_LMVM;
253a7e14dcfSSatish Balay   tao->ops->destroy = TaoDestroy_LMVM;
254a7e14dcfSSatish Balay 
2553c9e27cfSGeoffrey Irving   ierr = PetscNewLog(tao,&lmP);CHKERRQ(ierr);
256a7e14dcfSSatish Balay   lmP->D = 0;
257a7e14dcfSSatish Balay   lmP->M = 0;
258a7e14dcfSSatish Balay   lmP->Xold = 0;
259a7e14dcfSSatish Balay   lmP->Gold = 0;
260a9603a14SPatrick Farrell   lmP->H0   = NULL;
261cd929ea3SAlp Dener   lmP->recycle = PETSC_FALSE;
262a7e14dcfSSatish Balay 
263a7e14dcfSSatish Balay   tao->data = (void*)lmP;
2646552cf8aSJason Sarich   /* Override default settings (unless already changed) */
2656552cf8aSJason Sarich   if (!tao->max_it_changed) tao->max_it = 2000;
2666552cf8aSJason Sarich   if (!tao->max_funcs_changed) tao->max_funcs = 4000;
267a7e14dcfSSatish Balay 
268a7e14dcfSSatish Balay   ierr = TaoLineSearchCreate(((PetscObject)tao)->comm,&tao->linesearch);CHKERRQ(ierr);
26963b15415SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)tao->linesearch, (PetscObject)tao, 1);CHKERRQ(ierr);
270a7e14dcfSSatish Balay   ierr = TaoLineSearchSetType(tao->linesearch,morethuente_type);CHKERRQ(ierr);
271441846f8SBarry Smith   ierr = TaoLineSearchUseTaoRoutines(tao->linesearch,tao);CHKERRQ(ierr);
2725d527766SPatrick Farrell   ierr = TaoLineSearchSetOptionsPrefix(tao->linesearch,tao->hdr.prefix);CHKERRQ(ierr);
273cd929ea3SAlp Dener 
274cd929ea3SAlp Dener   ierr = KSPInitializePackage();CHKERRQ(ierr);
275cd929ea3SAlp Dener   ierr = MatCreate(((PetscObject)tao)->comm, &lmP->M);CHKERRQ(ierr);
276cd929ea3SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)lmP->M, (PetscObject)tao, 1);CHKERRQ(ierr);
27778e4361aSAlp Dener   ierr = MatSetType(lmP->M, MATLMVMBFGS);CHKERRQ(ierr);
278cd929ea3SAlp Dener   ierr = MatSetOptionsPrefix(lmP->M, "tao_lmvm_");CHKERRQ(ierr);
279a7e14dcfSSatish Balay   PetscFunctionReturn(0);
280a7e14dcfSSatish Balay }
281*13b46278SAlp Dener 
282*13b46278SAlp Dener PETSC_EXTERN PetscErrorCode TaoLMVMSetH0(Tao tao, Mat H0)
283*13b46278SAlp Dener {
284*13b46278SAlp Dener   TAO_LMVM       *lmP;
285*13b46278SAlp Dener   TAO_BLMVM      *blmP;
286*13b46278SAlp Dener   const TaoType  type;
287*13b46278SAlp Dener   PetscBool      is_lmvm, is_blmvm;
288*13b46278SAlp Dener   PetscErrorCode ierr;
289*13b46278SAlp Dener 
290*13b46278SAlp Dener   ierr = TaoGetType(tao, &type);CHKERRQ(ierr);
291*13b46278SAlp Dener   ierr = PetscStrcmp(type, TAOLMVM,  &is_lmvm);CHKERRQ(ierr);
292*13b46278SAlp Dener   ierr = PetscStrcmp(type, TAOBLMVM, &is_blmvm);CHKERRQ(ierr);
293*13b46278SAlp Dener 
294*13b46278SAlp Dener   if (is_lmvm) {
295*13b46278SAlp Dener     lmP = (TAO_LMVM *)tao->data;
296*13b46278SAlp Dener     ierr = PetscObjectReference((PetscObject)H0);CHKERRQ(ierr);
297*13b46278SAlp Dener     lmP->H0 = H0;
298*13b46278SAlp Dener   } else if (is_blmvm) {
299*13b46278SAlp Dener     blmP = (TAO_BLMVM *)tao->data;
300*13b46278SAlp Dener     ierr = PetscObjectReference((PetscObject)H0);CHKERRQ(ierr);
301*13b46278SAlp Dener     blmP->H0 = H0;
302*13b46278SAlp Dener   } else SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "This routine applies to TAO_LMVM and TAO_BLMVM.");
303*13b46278SAlp Dener   PetscFunctionReturn(0);
304*13b46278SAlp Dener }
305*13b46278SAlp Dener 
306*13b46278SAlp Dener PETSC_EXTERN PetscErrorCode TaoLMVMGetH0(Tao tao, Mat *H0)
307*13b46278SAlp Dener {
308*13b46278SAlp Dener   TAO_LMVM       *lmP;
309*13b46278SAlp Dener   TAO_BLMVM      *blmP;
310*13b46278SAlp Dener   const TaoType  type;
311*13b46278SAlp Dener   PetscBool      is_lmvm, is_blmvm;
312*13b46278SAlp Dener   Mat            M;
313*13b46278SAlp Dener 
314*13b46278SAlp Dener   PetscErrorCode ierr;
315*13b46278SAlp Dener 
316*13b46278SAlp Dener   ierr = TaoGetType(tao, &type);CHKERRQ(ierr);
317*13b46278SAlp Dener   ierr = PetscStrcmp(type, TAOLMVM,  &is_lmvm);CHKERRQ(ierr);
318*13b46278SAlp Dener   ierr = PetscStrcmp(type, TAOBLMVM, &is_blmvm);CHKERRQ(ierr);
319*13b46278SAlp Dener 
320*13b46278SAlp Dener   if (is_lmvm) {
321*13b46278SAlp Dener     lmP = (TAO_LMVM *)tao->data;
322*13b46278SAlp Dener     M = lmP->M;
323*13b46278SAlp Dener   } else if (is_blmvm) {
324*13b46278SAlp Dener     blmP = (TAO_BLMVM *)tao->data;
325*13b46278SAlp Dener     M = blmP->M;
326*13b46278SAlp Dener   } else SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "This routine applies to TAO_LMVM and TAO_BLMVM.");
327*13b46278SAlp Dener   ierr = MatLMVMGetJ0(M, H0);CHKERRQ(ierr);
328*13b46278SAlp Dener   PetscFunctionReturn(0);
329*13b46278SAlp Dener }
330*13b46278SAlp Dener 
331*13b46278SAlp Dener PETSC_EXTERN PetscErrorCode TaoLMVMGetH0KSP(Tao tao, KSP *ksp)
332*13b46278SAlp Dener {
333*13b46278SAlp Dener   TAO_LMVM       *lmP;
334*13b46278SAlp Dener   TAO_BLMVM      *blmP;
335*13b46278SAlp Dener   const TaoType  type;
336*13b46278SAlp Dener   PetscBool      is_lmvm, is_blmvm;
337*13b46278SAlp Dener   Mat            M;
338*13b46278SAlp Dener   PetscErrorCode ierr;
339*13b46278SAlp Dener 
340*13b46278SAlp Dener   ierr = TaoGetType(tao, &type);CHKERRQ(ierr);
341*13b46278SAlp Dener   ierr = PetscStrcmp(type, TAOLMVM,  &is_lmvm);CHKERRQ(ierr);
342*13b46278SAlp Dener   ierr = PetscStrcmp(type, TAOBLMVM, &is_blmvm);CHKERRQ(ierr);
343*13b46278SAlp Dener 
344*13b46278SAlp Dener   if (is_lmvm) {
345*13b46278SAlp Dener     lmP = (TAO_LMVM *)tao->data;
346*13b46278SAlp Dener     M = lmP->M;
347*13b46278SAlp Dener   } else if (is_blmvm) {
348*13b46278SAlp Dener     blmP = (TAO_BLMVM *)tao->data;
349*13b46278SAlp Dener     M = blmP->M;
350*13b46278SAlp Dener   } else SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "This routine applies to TAO_LMVM and TAO_BLMVM.");
351*13b46278SAlp Dener   ierr = MatLMVMGetJ0KSP(M, ksp);CHKERRQ(ierr);
352*13b46278SAlp Dener   PetscFunctionReturn(0);
353*13b46278SAlp Dener }