xref: /petsc/src/snes/linesearch/interface/linesearch.c (revision bbd5d0b317af04eb83c39e72581bf86c64bd741a)
1 #include <private/linesearchimpl.h> /*I "petsclinesearch.h" I*/
2 
3 PetscBool  LineSearchRegisterAllCalled = PETSC_FALSE;
4 PetscFList LineSearchList              = PETSC_NULL;
5 
6 PetscClassId   LineSearch_CLASSID;
7 PetscLogEvent  LineSearch_Apply;
8 
9 #undef __FUNCT__
10 #define __FUNCT__ "LineSearchCreate"
11 PetscErrorCode LineSearchCreate(MPI_Comm comm, LineSearch * outlinesearch) {
12   PetscErrorCode ierr;
13   LineSearch     linesearch;
14   PetscFunctionBegin;
15   ierr = PetscHeaderCreate(linesearch, _p_LineSearch,struct _LineSearchOps,LineSearch_CLASSID, 0,
16                            "LineSearch","Line-search method","LineSearch",comm,LineSearchDestroy,LineSearchView);CHKERRQ(ierr);
17 
18   linesearch->ops->precheckstep = PETSC_NULL;
19   linesearch->ops->postcheckstep = PETSC_NULL;
20 
21   linesearch->lambda        = 1.0;
22   linesearch->fnorm         = 1.0;
23   linesearch->ynorm         = 1.0;
24   linesearch->xnorm         = 1.0;
25   linesearch->success       = PETSC_TRUE;
26   linesearch->norms         = PETSC_TRUE;
27   linesearch->keeplambda    = PETSC_FALSE;
28   linesearch->damping       = 1.0;
29   linesearch->maxstep       = 1e8;
30   linesearch->steptol       = 1e-12;
31   linesearch->precheckctx   = PETSC_NULL;
32   linesearch->postcheckctx  = PETSC_NULL;
33   linesearch->max_its       = 1;
34   linesearch->setupcalled   = PETSC_FALSE;
35   *outlinesearch            = linesearch;
36   PetscFunctionReturn(0);
37 }
38 
39 #undef __FUNCT__
40 #define __FUNCT__ "LineSearchSetUp"
41 PetscErrorCode LineSearchSetUp(LineSearch linesearch) {
42   PetscErrorCode ierr;
43   PetscFunctionBegin;
44 
45   if (!((PetscObject)linesearch)->type_name) {
46     ierr = LineSearchSetType(linesearch,LINESEARCHBASIC);CHKERRQ(ierr);
47   }
48 
49   if (!linesearch->setupcalled) {
50     ierr = VecDuplicate(linesearch->vec_sol, &linesearch->vec_sol_new);CHKERRQ(ierr);
51     ierr = VecDuplicate(linesearch->vec_func, &linesearch->vec_func_new);CHKERRQ(ierr);
52     if (linesearch->ops->setup) {
53       ierr = (*linesearch->ops->setup)(linesearch);CHKERRQ(ierr);
54     }
55     linesearch->lambda = linesearch->damping;
56     linesearch->setupcalled = PETSC_TRUE;
57   }
58   PetscFunctionReturn(0);
59 }
60 
61 #undef __FUNCT__
62 #define __FUNCT__ "LineSearchReset"
63 PetscErrorCode LineSearchReset(LineSearch linesearch) {
64   PetscErrorCode ierr;
65   PetscFunctionBegin;
66   if (linesearch->ops->reset) {
67     (*linesearch->ops->reset)(linesearch);
68   }
69   ierr = VecDestroy(&linesearch->vec_sol_new);CHKERRQ(ierr);
70   ierr = VecDestroy(&linesearch->vec_func_new);CHKERRQ(ierr);
71 
72   ierr = VecDestroyVecs(linesearch->nwork, &linesearch->work);CHKERRQ(ierr);
73   linesearch->nwork = 0;
74   linesearch->setupcalled = PETSC_FALSE;
75   PetscFunctionReturn(0);
76 }
77 
78 #undef __FUNCT__
79 #define __FUNCT__ "LineSearchPreCheck"
80 PetscErrorCode LineSearchPreCheck(LineSearch linesearch, PetscBool * changed)
81 {
82   PetscErrorCode ierr;
83   PetscFunctionBegin;
84   *changed = PETSC_FALSE;
85   if (linesearch->ops->precheckstep) {
86     ierr = (*linesearch->ops->precheckstep)(linesearch, linesearch->vec_sol, linesearch->vec_update, changed);CHKERRQ(ierr);
87   }
88   PetscFunctionReturn(0);
89 }
90 
91 #undef __FUNCT__
92 #define __FUNCT__ "LineSearchPostCheck"
93 PetscErrorCode LineSearchPostCheck(LineSearch linesearch, PetscBool * changed_W, PetscBool * changed_Y)
94 {
95   PetscErrorCode ierr;
96   PetscFunctionBegin;
97   *changed_Y = PETSC_FALSE;
98   *changed_W = PETSC_FALSE;
99   if (linesearch->ops->postcheckstep) {
100     ierr = (*linesearch->ops->postcheckstep)(linesearch, linesearch->vec_sol, linesearch->vec_sol_new, linesearch->vec_update, changed_W, changed_Y);CHKERRQ(ierr);
101   }
102   PetscFunctionReturn(0);
103 }
104 
105 #undef __FUNCT__
106 #define __FUNCT__ "LineSearchApply"
107 PetscErrorCode LineSearchApply(LineSearch linesearch, Vec X, Vec F, PetscReal * fnorm, Vec Y) {
108   PetscErrorCode ierr;
109   PetscFunctionBegin;
110 
111   /* check the pointers */
112   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
113   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
114   PetscValidHeaderSpecific(F,VEC_CLASSID,3);
115   PetscValidHeaderSpecific(Y,VEC_CLASSID,4);
116 
117   linesearch->success = PETSC_TRUE;
118 
119   linesearch->vec_sol = X;
120   linesearch->vec_update = Y;
121   linesearch->vec_func = F;
122 
123   ierr = LineSearchSetUp(linesearch);CHKERRQ(ierr);
124 
125   if (!linesearch->keeplambda)
126     linesearch->lambda = linesearch->damping; /* set the initial guess to lambda */
127 
128   if (fnorm) {
129     linesearch->fnorm = *fnorm;
130   } else {
131     ierr = VecNorm(F, NORM_2, &linesearch->fnorm);CHKERRQ(ierr);
132   }
133 
134   ierr = PetscLogEventBegin(LineSearch_Apply,linesearch,X,F,Y);CHKERRQ(ierr);
135 
136   ierr = (*linesearch->ops->apply)(linesearch);CHKERRQ(ierr);
137 
138   ierr = PetscLogEventEnd(LineSearch_Apply,linesearch,X,F,Y);CHKERRQ(ierr);
139 
140   if (fnorm)
141     *fnorm = linesearch->fnorm;
142   PetscFunctionReturn(0);
143 }
144 
145 #undef __FUNCT__
146 #define __FUNCT__ "LineSearchDestroy"
147 PetscErrorCode LineSearchDestroy(LineSearch * linesearch) {
148   PetscErrorCode ierr;
149   PetscFunctionBegin;
150   if (!*linesearch) PetscFunctionReturn(0);
151   PetscValidHeaderSpecific((*linesearch),LineSearch_CLASSID,1);
152   if (--((PetscObject)(*linesearch))->refct > 0) {*linesearch = 0; PetscFunctionReturn(0);}
153   ierr = PetscObjectDepublish((*linesearch));CHKERRQ(ierr);
154   ierr = LineSearchReset(*linesearch);
155   if ((*linesearch)->ops->destroy) {
156     (*linesearch)->ops->destroy(*linesearch);
157   }
158   ierr = PetscViewerDestroy(&(*linesearch)->monitor);CHKERRQ(ierr);
159   ierr = PetscHeaderDestroy(linesearch);CHKERRQ(ierr);
160   PetscFunctionReturn(0);
161 }
162 
163 #undef __FUNCT__
164 #define __FUNCT__ "LineSearchSetMonitor"
165 /*@C
166    SNESLineSearchSetMonitor - Prints information about the progress or lack of progress of the line search
167 
168    Input Parameters:
169 +  snes - nonlinear context obtained from SNESCreate()
170 -  flg - PETSC_TRUE to monitor the line search
171 
172    Logically Collective on SNES
173 
174    Options Database:
175 .   -snes_ls_monitor
176 
177    Level: intermediate
178 
179 
180 .seealso: SNESLineSearchSet(), SNESLineSearchSetPostCheck(), SNESSetUpdate()
181 @*/
182 PetscErrorCode  LineSearchSetMonitor(LineSearch linesearch,PetscBool flg)
183 {
184 
185   PetscErrorCode ierr;
186   PetscFunctionBegin;
187   if (flg && !linesearch->monitor) {
188     ierr = PetscViewerASCIIOpen(((PetscObject)linesearch)->comm,"stdout",&linesearch->monitor);CHKERRQ(ierr);
189   } else if (!flg && linesearch->monitor) {
190     ierr = PetscViewerDestroy(&linesearch->monitor);CHKERRQ(ierr);
191   }
192   PetscFunctionReturn(0);
193 }
194 
195 #undef __FUNCT__
196 #define __FUNCT__ "LineSearchSetFromOptions"
197 PetscErrorCode LineSearchSetFromOptions(LineSearch linesearch) {
198   PetscErrorCode ierr;
199   const char     *deft = LINESEARCHBASIC;
200   char           type[256];
201   PetscBool      flg, set;
202   PetscFunctionBegin;
203   if (!LineSearchRegisterAllCalled) {ierr = LineSearchRegisterAll(PETSC_NULL);CHKERRQ(ierr);}
204 
205   ierr = PetscObjectOptionsBegin((PetscObject)linesearch);CHKERRQ(ierr);
206   if (((PetscObject)linesearch)->type_name) {
207     deft = ((PetscObject)linesearch)->type_name;
208   }
209   ierr = PetscOptionsList("-linesearch_type","Line-search method","LineSearchSetType",LineSearchList,deft,type,256,&flg);CHKERRQ(ierr);
210   if (flg) {
211     ierr = LineSearchSetType(linesearch,type);CHKERRQ(ierr);
212   } else if (!((PetscObject)linesearch)->type_name) {
213     ierr = LineSearchSetType(linesearch,deft);CHKERRQ(ierr);
214   }
215   if (linesearch->ops->setfromoptions) {
216     (*linesearch->ops->setfromoptions)(linesearch);CHKERRQ(ierr);
217   }
218 
219     ierr = PetscOptionsBool("-linesearch_monitor","Print progress of line searches","SNESLineSearchSetMonitor",
220                             linesearch->monitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr);
221     if (set) {ierr = LineSearchSetMonitor(linesearch,flg);CHKERRQ(ierr);}
222 
223   ierr = PetscOptionsReal("-linesearch_damping","Line search damping and initial step guess","LineSearchSetDamping",linesearch->damping,&linesearch->damping,0);CHKERRQ(ierr);
224   ierr = PetscOptionsBool("-linesearch_norms","Compute final norms in line search","LineSearchSetDamping",linesearch->norms,&linesearch->norms,0);CHKERRQ(ierr);
225   ierr = PetscOptionsBool("-linesearch_keeplambda","Use previous lambda as damping","LineSearchSetDamping",linesearch->keeplambda,&linesearch->keeplambda,0);CHKERRQ(ierr);
226   ierr = PetscOptionsInt("-linesearch_max_it","Maximum iterations for iterative line searches","",linesearch->max_its,&linesearch->max_its,0);CHKERRQ(ierr);
227   ierr = PetscObjectProcessOptionsHandlers((PetscObject)linesearch);CHKERRQ(ierr);
228   ierr = PetscOptionsEnd();CHKERRQ(ierr);
229   PetscFunctionReturn(0);
230 }
231 
232 #undef __FUNCT__
233 #define __FUNCT__ "LineSearchView"
234 PetscErrorCode LineSearchView(LineSearch linesearch) {
235   PetscFunctionBegin;
236   PetscFunctionReturn(0);
237 }
238 
239 #undef __FUNCT__
240 #define __FUNCT__ "LineSearchSetType"
241 PetscErrorCode LineSearchSetType(LineSearch linesearch, const LineSearchType type)
242 {
243 
244   PetscErrorCode ierr,(*r)(LineSearch);
245   PetscBool      match;
246 
247   PetscFunctionBegin;
248   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
249   PetscValidCharPointer(type,2);
250 
251   ierr = PetscTypeCompare((PetscObject)linesearch,type,&match);CHKERRQ(ierr);
252   if (match) PetscFunctionReturn(0);
253 
254   ierr =  PetscFListFind(LineSearchList,((PetscObject)linesearch)->comm,type,PETSC_TRUE,(void (**)(void)) &r);CHKERRQ(ierr);
255   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested Line Search type %s",type);
256   /* Destroy the previous private linesearch context */
257   if (linesearch->ops->destroy) {
258     ierr = (*(linesearch)->ops->destroy)(linesearch);CHKERRQ(ierr);
259     linesearch->ops->destroy = PETSC_NULL;
260   }
261   /* Reinitialize function pointers in LineSearchOps structure */
262   linesearch->ops->apply          = 0;
263   linesearch->ops->view           = 0;
264   linesearch->ops->setfromoptions = 0;
265   linesearch->ops->destroy        = 0;
266 
267   ierr = PetscObjectChangeTypeName((PetscObject)linesearch,type);CHKERRQ(ierr);
268   ierr = (*r)(linesearch);CHKERRQ(ierr);
269 #if defined(PETSC_HAVE_AMS)
270   if (PetscAMSPublishAll) {
271     ierr = PetscObjectAMSPublish((PetscObject)linesearch);CHKERRQ(ierr);
272   }
273 #endif
274   PetscFunctionReturn(0);
275 }
276 
277 #undef __FUNCT__
278 #define __FUNCT__ "LineSearchSetSNES"
279 PetscErrorCode  LineSearchSetSNES(LineSearch linesearch, SNES snes){
280   PetscFunctionBegin;
281   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
282   PetscValidHeaderSpecific(snes,SNES_CLASSID,2);
283   linesearch->snes = snes;
284   PetscFunctionReturn(0);
285 }
286 
287 #undef __FUNCT__
288 #define __FUNCT__ "LineSearchGetSNES"
289 PetscErrorCode  LineSearchGetSNES(LineSearch linesearch, SNES *snes){
290   PetscFunctionBegin;
291   *snes = linesearch->snes;
292   PetscFunctionReturn(0);
293 }
294 
295 
296 #undef __FUNCT__
297 #define __FUNCT__ "LineSearchGetNorms"
298 PetscErrorCode  LineSearchGetNorms(LineSearch linesearch, PetscReal * xnorm, PetscReal * fnorm, PetscReal * ynorm)
299 {
300   PetscFunctionBegin;
301   if (xnorm) {
302     *xnorm = linesearch->xnorm;
303   }
304   if (fnorm) {
305     *fnorm = linesearch->fnorm;
306   }
307   if (ynorm) {
308     *ynorm = linesearch->ynorm;
309   }
310   PetscFunctionReturn(0);
311 }
312 
313 #undef __FUNCT__
314 #define __FUNCT__ "LineSearchAppendOptionsPrefix"
315 /*@C
316    LineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all
317    SNES options in the database.
318 
319    Logically Collective on SNES
320 
321    Input Parameters:
322 +  snes - the SNES context
323 -  prefix - the prefix to prepend to all option names
324 
325    Notes:
326    A hyphen (-) must NOT be given at the beginning of the prefix name.
327    The first character of all runtime options is AUTOMATICALLY the hyphen.
328 
329    Level: advanced
330 
331 .keywords: SNES, append, options, prefix, database
332 
333 .seealso: SNESGetOptionsPrefix()
334 @*/
335 PetscErrorCode  LineSearchAppendOptionsPrefix(LineSearch linesearch,const char prefix[])
336 {
337   PetscErrorCode ierr;
338 
339   PetscFunctionBegin;
340   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
341   ierr = PetscObjectAppendOptionsPrefix((PetscObject)linesearch,prefix);CHKERRQ(ierr);
342   PetscFunctionReturn(0);
343 }
344 
345 #undef __FUNCT__
346 #define __FUNCT__ "LineSearchGetOptionsPrefix"
347 /*@C
348    LineSearchGetOptionsPrefix - Sets the prefix used for searching for all
349    SNES options in the database.
350 
351    Not Collective
352 
353    Input Parameter:
354 .  snes - the SNES context
355 
356    Output Parameter:
357 .  prefix - pointer to the prefix string used
358 
359    Notes: On the fortran side, the user should pass in a string 'prefix' of
360    sufficient length to hold the prefix.
361 
362    Level: advanced
363 
364 .keywords: SNES, get, options, prefix, database
365 
366 .seealso: SNESAppendOptionsPrefix()
367 @*/
368 PetscErrorCode  LineSearchGetOptionsPrefix(LineSearch linesearch,const char *prefix[])
369 {
370   PetscErrorCode ierr;
371 
372   PetscFunctionBegin;
373   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
374   ierr = PetscObjectGetOptionsPrefix((PetscObject)linesearch,prefix);CHKERRQ(ierr);
375   PetscFunctionReturn(0);
376 }
377 
378 #undef __FUNCT__
379 #define __FUNCT__ "LineSearchGetWork"
380 PetscErrorCode  LineSearchGetWork(LineSearch linesearch, PetscInt nwork)
381 {
382   PetscErrorCode ierr;
383   PetscFunctionBegin;
384   if (linesearch->vec_sol) {
385     ierr = VecDuplicateVecs(linesearch->vec_sol, nwork, &linesearch->work);CHKERRQ(ierr);
386   } else {
387     SETERRQ(((PetscObject)linesearch)->comm, PETSC_ERR_USER, "Cannot get linesearch work-vectors without setting a solution vec!");
388   }
389   PetscFunctionReturn(0);
390 }
391 
392 #undef __FUNCT__
393 #define __FUNCT__ "LineSearchGetSuccess"
394 PetscErrorCode  LineSearchGetSuccess(LineSearch linesearch, PetscBool *success)
395 {
396   PetscFunctionBegin;
397   if (success) {
398     *success = linesearch->success;
399   }
400   PetscFunctionReturn(0);
401 }
402 
403 #undef __FUNCT__
404 #define __FUNCT__ "LineSearchRegister"
405 /*@C
406   LineSearchRegister - See LineSearchRegisterDynamic()
407 
408   Level: advanced
409 @*/
410 PetscErrorCode  LineSearchRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(LineSearch))
411 {
412   char           fullname[PETSC_MAX_PATH_LEN];
413   PetscErrorCode ierr;
414 
415   PetscFunctionBegin;
416   ierr = PetscFListConcat(path,name,fullname);CHKERRQ(ierr);
417   ierr = PetscFListAdd(&LineSearchList,sname,fullname,(void (*)(void))function);CHKERRQ(ierr);
418   PetscFunctionReturn(0);
419 }
420