xref: /petsc/src/snes/impls/qn/qn.c (revision 2c71b3e237ead271e4f3aa1505f92bf476e3413d)
1af0996ceSBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/
2fced5a79SAsbjørn Nilsen Riseth #include <petscdm.h>
34b11644fSPeter Brune 
48e231d97SPeter Brune #define H(i,j)  qn->dXdFmat[i*qn->m + j]
58e231d97SPeter Brune 
69e5d0892SLisandro Dalcin const char *const SNESQNScaleTypes[] =        {"DEFAULT","NONE","SCALAR","DIAGONAL","JACOBIAN","SNESQNScaleType","SNES_QN_SCALING_",NULL};
79e5d0892SLisandro Dalcin const char *const SNESQNRestartTypes[] =      {"DEFAULT","NONE","POWELL","PERIODIC","SNESQNRestartType","SNES_QN_RESTART_",NULL};
89e5d0892SLisandro Dalcin const char *const SNESQNTypes[] =             {"LBFGS","BROYDEN","BADBROYDEN","SNESQNType","SNES_QN_",NULL};
9b8840d6bSPeter Brune 
104b11644fSPeter Brune typedef struct {
1192f76d53SAlp Dener   Mat               B;                    /* Quasi-Newton approximation Matrix (MATLMVM) */
128e231d97SPeter Brune   PetscInt          m;                    /* The number of kept previous steps */
135c7a0a03SPeter Brune   PetscReal         *lambda;              /* The line search history of the method */
1492f76d53SAlp Dener   PetscBool         monflg;
1544f7e39eSPeter Brune   PetscViewer       monitor;
166bf1b2e5SPeter Brune   PetscReal         powell_gamma;         /* Powell angle restart condition */
17b21d5a53SPeter Brune   PetscReal         scaling;              /* scaling of H0 */
18b8840d6bSPeter Brune   SNESQNType        type;                 /* the type of quasi-newton method used */
1988f769c5SPeter Brune   SNESQNScaleType   scale_type;           /* the type of scaling used */
200c777b0cSPeter Brune   SNESQNRestartType restart_type;         /* determine the frequency and type of restart conditions */
219f83bee8SJed Brown } SNES_QN;
224b11644fSPeter Brune 
234b11644fSPeter Brune static PetscErrorCode SNESSolve_QN(SNES snes)
244b11644fSPeter Brune {
254b11644fSPeter Brune   PetscErrorCode       ierr;
269f83bee8SJed Brown   SNES_QN              *qn = (SNES_QN*) snes->data;
2715f5eeeaSPeter Brune   Vec                  X,Xold;
280a3905e1SPeter Brune   Vec                  F,W;
2947f26062SPeter Brune   Vec                  Y,D,Dold;
30b8840d6bSPeter Brune   PetscInt             i, i_r;
31335fb975SPeter Brune   PetscReal            fnorm,xnorm,ynorm,gnorm;
32422a814eSBarry Smith   SNESLineSearchReason lssucceed;
3392f76d53SAlp Dener   PetscBool            badstep,powell,periodic;
341c6523dcSPeter Brune   PetscScalar          DolddotD,DolddotDold;
35b7281c8aSPeter Brune   SNESConvergedReason  reason;
360ecc9e1dSPeter Brune 
3784c577daSBarry Smith   /* basically just a regular newton's method except for the application of the Jacobian */
384b11644fSPeter Brune 
396e111a19SKarl Rupp   PetscFunctionBegin;
40*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(snes->xl || snes->xu || snes->ops->computevariablebounds,PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE, "SNES solver %s does not support bounds", ((PetscObject)snes)->type_name);
41c579b300SPatrick Farrell 
42fffbeea8SBarry Smith   ierr = PetscCitationsRegister(SNESCitation,&SNEScite);CHKERRQ(ierr);
439f3a0142SPeter Brune   F    = snes->vec_func;                /* residual vector */
443af51624SPeter Brune   Y    = snes->vec_sol_update;          /* search direction generated by J^-1D*/
450a3905e1SPeter Brune   W    = snes->work[3];
46b8840d6bSPeter Brune   X    = snes->vec_sol;                 /* solution vector */
47335fb975SPeter Brune   Xold = snes->work[0];
483af51624SPeter Brune 
493af51624SPeter Brune   /* directions generated by the preconditioned problem with F_pre = F or x - M(x, b) */
50335fb975SPeter Brune   D    = snes->work[1];
51335fb975SPeter Brune   Dold = snes->work[2];
524b11644fSPeter Brune 
534b11644fSPeter Brune   snes->reason = SNES_CONVERGED_ITERATING;
544b11644fSPeter Brune 
55e04113cfSBarry Smith   ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
564b11644fSPeter Brune   snes->iter = 0;
574b11644fSPeter Brune   snes->norm = 0.;
58e04113cfSBarry Smith   ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
5947f26062SPeter Brune 
60efd4aadfSBarry Smith   if (snes->npc && snes->npcside== PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
61be95d8f1SBarry Smith     ierr = SNESApplyNPC(snes,X,NULL,F);CHKERRQ(ierr);
62efd4aadfSBarry Smith     ierr = SNESGetConvergedReason(snes->npc,&reason);CHKERRQ(ierr);
63b7281c8aSPeter Brune     if (reason < 0  && reason != SNES_DIVERGED_MAX_IT) {
64b7281c8aSPeter Brune       snes->reason = SNES_DIVERGED_INNER;
65b7281c8aSPeter Brune       PetscFunctionReturn(0);
66b7281c8aSPeter Brune     }
6747f26062SPeter Brune     ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr);
6847f26062SPeter Brune   } else {
69e4ed7901SPeter Brune     if (!snes->vec_func_init_set) {
7015f5eeeaSPeter Brune       ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
711aa26658SKarl Rupp     } else snes->vec_func_init_set = PETSC_FALSE;
72c1c75074SPeter Brune 
7347f26062SPeter Brune     ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr);
74422a814eSBarry Smith     SNESCheckFunctionNorm(snes,fnorm);
7547f26062SPeter Brune   }
76efd4aadfSBarry Smith   if (snes->npc && snes->npcside== PC_LEFT && snes->functype == SNES_FUNCTION_UNPRECONDITIONED) {
77be95d8f1SBarry Smith     ierr = SNESApplyNPC(snes,X,F,D);CHKERRQ(ierr);
78efd4aadfSBarry Smith     ierr = SNESGetConvergedReason(snes->npc,&reason);CHKERRQ(ierr);
79b7281c8aSPeter Brune     if (reason < 0  && reason != SNES_DIVERGED_MAX_IT) {
80b7281c8aSPeter Brune       snes->reason = SNES_DIVERGED_INNER;
81b7281c8aSPeter Brune       PetscFunctionReturn(0);
82b7281c8aSPeter Brune     }
8347f26062SPeter Brune   } else {
8447f26062SPeter Brune     ierr = VecCopy(F,D);CHKERRQ(ierr);
8547f26062SPeter Brune   }
86b28a06ddSPeter Brune 
87e04113cfSBarry Smith   ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
884b11644fSPeter Brune   snes->norm = fnorm;
89e04113cfSBarry Smith   ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
90a71f0d7dSBarry Smith   ierr       = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr);
914b11644fSPeter Brune   ierr       = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
924b11644fSPeter Brune 
934b11644fSPeter Brune   /* test convergence */
944b11644fSPeter Brune   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
954b11644fSPeter Brune   if (snes->reason) PetscFunctionReturn(0);
9670d3b23bSPeter Brune 
97efd4aadfSBarry Smith   if (snes->npc && snes->npcside== PC_RIGHT) {
98efd4aadfSBarry Smith     ierr = PetscLogEventBegin(SNES_NPCSolve,snes->npc,X,0,0);CHKERRQ(ierr);
99efd4aadfSBarry Smith     ierr = SNESSolve(snes->npc,snes->vec_rhs,X);CHKERRQ(ierr);
100efd4aadfSBarry Smith     ierr = PetscLogEventEnd(SNES_NPCSolve,snes->npc,X,0,0);CHKERRQ(ierr);
101efd4aadfSBarry Smith     ierr = SNESGetConvergedReason(snes->npc,&reason);CHKERRQ(ierr);
102ddd40ce5SPeter Brune     if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) {
103ddd40ce5SPeter Brune       snes->reason = SNES_DIVERGED_INNER;
104ddd40ce5SPeter Brune       PetscFunctionReturn(0);
105ddd40ce5SPeter Brune     }
106be95d8f1SBarry Smith     ierr = SNESGetNPCFunction(snes,F,&fnorm);CHKERRQ(ierr);
1073cf07b75SPeter Brune     ierr = VecCopy(F,D);CHKERRQ(ierr);
1083cf07b75SPeter Brune   }
1093cf07b75SPeter Brune 
11001fe78eaSStefano Zampini   /* general purpose update */
11101fe78eaSStefano Zampini   if (snes->ops->update) {
11201fe78eaSStefano Zampini     ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
11301fe78eaSStefano Zampini   }
11401fe78eaSStefano Zampini 
115f8e15203SPeter Brune   /* scale the initial update */
1160c777b0cSPeter Brune   if (qn->scale_type == SNES_QN_SCALE_JACOBIAN) {
117d1e9a80fSBarry Smith     ierr = SNESComputeJacobian(snes,X,snes->jacobian,snes->jacobian_pre);CHKERRQ(ierr);
11807b62357SFande Kong     SNESCheckJacobianDomainerror(snes);
119aeb49b86SAsbjørn Nilsen Riseth     ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre);CHKERRQ(ierr);
12092f76d53SAlp Dener     ierr = MatLMVMSetJ0KSP(qn->B, snes->ksp);CHKERRQ(ierr);
1210ecc9e1dSPeter Brune   }
1220ecc9e1dSPeter Brune 
1235ba6227bSPeter Brune   for (i = 0, i_r = 0; i < snes->max_its; i++, i_r++) {
12492f76d53SAlp Dener     /* update QN approx and calculate step */
12592f76d53SAlp Dener     ierr = MatLMVMUpdate(qn->B, X, D);CHKERRQ(ierr);
12692f76d53SAlp Dener     ierr = MatSolve(qn->B, D, Y);CHKERRQ(ierr);
12792f76d53SAlp Dener 
12870d3b23bSPeter Brune     /* line search for lambda */
12970d3b23bSPeter Brune     ynorm = 1; gnorm = fnorm;
1300a3905e1SPeter Brune     ierr  = VecCopy(D, Dold);CHKERRQ(ierr);
13115f5eeeaSPeter Brune     ierr  = VecCopy(X, Xold);CHKERRQ(ierr);
132f1c6b773SPeter Brune     ierr  = SNESLineSearchApply(snes->linesearch, X, F, &fnorm, Y);CHKERRQ(ierr);
1339f3a0142SPeter Brune     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
134422a814eSBarry Smith     ierr = SNESLineSearchGetReason(snes->linesearch, &lssucceed);CHKERRQ(ierr);
135422a814eSBarry Smith     ierr = SNESLineSearchGetNorms(snes->linesearch, &xnorm, &fnorm, &ynorm);CHKERRQ(ierr);
13692f76d53SAlp Dener     badstep = PETSC_FALSE;
137422a814eSBarry Smith     if (lssucceed) {
1389f3a0142SPeter Brune       if (++snes->numFailures >= snes->maxFailures) {
1399f3a0142SPeter Brune         snes->reason = SNES_DIVERGED_LINE_SEARCH;
1409f3a0142SPeter Brune         break;
1419f3a0142SPeter Brune       }
14292f76d53SAlp Dener       badstep = PETSC_TRUE;
1430ecc9e1dSPeter Brune     }
1443af51624SPeter Brune 
14588d374b2SPeter Brune     /* convergence monitoring */
1467d3de750SJacob Faibussowitsch     ierr = PetscInfo(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",(double)fnorm,(double)gnorm,(double)ynorm,(int)lssucceed);CHKERRQ(ierr);
147b21d5a53SPeter Brune 
148efd4aadfSBarry Smith     if (snes->npc && snes->npcside== PC_RIGHT) {
149efd4aadfSBarry Smith       ierr = PetscLogEventBegin(SNES_NPCSolve,snes->npc,X,0,0);CHKERRQ(ierr);
150efd4aadfSBarry Smith       ierr = SNESSolve(snes->npc,snes->vec_rhs,X);CHKERRQ(ierr);
151efd4aadfSBarry Smith       ierr = PetscLogEventEnd(SNES_NPCSolve,snes->npc,X,0,0);CHKERRQ(ierr);
152efd4aadfSBarry Smith       ierr = SNESGetConvergedReason(snes->npc,&reason);CHKERRQ(ierr);
153ddd40ce5SPeter Brune       if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) {
154ddd40ce5SPeter Brune         snes->reason = SNES_DIVERGED_INNER;
155ddd40ce5SPeter Brune         PetscFunctionReturn(0);
156ddd40ce5SPeter Brune       }
157be95d8f1SBarry Smith       ierr = SNESGetNPCFunction(snes,F,&fnorm);CHKERRQ(ierr);
158b28a06ddSPeter Brune     }
159b28a06ddSPeter Brune 
160360c497dSPeter Brune     ierr = SNESSetIterationNumber(snes, i+1);CHKERRQ(ierr);
16171dbe336SPeter Brune     snes->norm = fnorm;
162c1e67a49SFande Kong     snes->xnorm = xnorm;
163c1e67a49SFande Kong     snes->ynorm = ynorm;
164360c497dSPeter Brune 
165a71f0d7dSBarry Smith     ierr = SNESLogConvergenceHistory(snes,snes->norm,snes->iter);CHKERRQ(ierr);
1668409ca45SMatthew G Knepley     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
16792f76d53SAlp Dener 
1684b11644fSPeter Brune     /* set parameter for default relative tolerance convergence test */
169d484d688SPeter Brune     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
1704b11644fSPeter Brune     if (snes->reason) PetscFunctionReturn(0);
171efd4aadfSBarry Smith     if (snes->npc && snes->npcside== PC_LEFT && snes->functype == SNES_FUNCTION_UNPRECONDITIONED) {
172be95d8f1SBarry Smith       ierr = SNESApplyNPC(snes,X,F,D);CHKERRQ(ierr);
173efd4aadfSBarry Smith       ierr = SNESGetConvergedReason(snes->npc,&reason);CHKERRQ(ierr);
174b7281c8aSPeter Brune       if (reason < 0  && reason != SNES_DIVERGED_MAX_IT) {
175b7281c8aSPeter Brune         snes->reason = SNES_DIVERGED_INNER;
176b7281c8aSPeter Brune         PetscFunctionReturn(0);
177b7281c8aSPeter Brune       }
17888d374b2SPeter Brune     } else {
17988d374b2SPeter Brune       ierr = VecCopy(F, D);CHKERRQ(ierr);
18088d374b2SPeter Brune     }
18101fe78eaSStefano Zampini 
18201fe78eaSStefano Zampini     /* general purpose update */
18301fe78eaSStefano Zampini     if (snes->ops->update) {
18401fe78eaSStefano Zampini       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
18501fe78eaSStefano Zampini     }
18601fe78eaSStefano Zampini 
18792f76d53SAlp Dener     /* restart conditions */
1880c777b0cSPeter Brune     powell = PETSC_FALSE;
1896bdcc836SBarry Smith     if (qn->restart_type == SNES_QN_RESTART_POWELL && i_r > 1) {
1906bdcc836SBarry Smith       /* check restart by Powell's Criterion: |F^T H_0 Fold| > powell_gamma * |Fold^T H_0 Fold| */
19123c918e7SPeter Brune       if (qn->scale_type == SNES_QN_SCALE_JACOBIAN) {
19223c918e7SPeter Brune         ierr = MatMult(snes->jacobian_pre,Dold,W);CHKERRQ(ierr);
19323c918e7SPeter Brune       } else {
19423c918e7SPeter Brune         ierr = VecCopy(Dold,W);CHKERRQ(ierr);
19523c918e7SPeter Brune       }
19623c918e7SPeter Brune       ierr = VecDotBegin(W, Dold, &DolddotDold);CHKERRQ(ierr);
19723c918e7SPeter Brune       ierr = VecDotBegin(W, D, &DolddotD);CHKERRQ(ierr);
19823c918e7SPeter Brune       ierr = VecDotEnd(W, Dold, &DolddotDold);CHKERRQ(ierr);
19923c918e7SPeter Brune       ierr = VecDotEnd(W, D, &DolddotD);CHKERRQ(ierr);
2000c777b0cSPeter Brune       if (PetscAbs(PetscRealPart(DolddotD)) > qn->powell_gamma*PetscAbs(PetscRealPart(DolddotDold))) powell = PETSC_TRUE;
2010c777b0cSPeter Brune     }
2020c777b0cSPeter Brune     periodic = PETSC_FALSE;
203b8840d6bSPeter Brune     if (qn->restart_type == SNES_QN_RESTART_PERIODIC) {
204b8840d6bSPeter Brune       if (i_r>qn->m-1) periodic = PETSC_TRUE;
2050c777b0cSPeter Brune     }
2060c777b0cSPeter Brune     /* restart if either powell or periodic restart is satisfied. */
20792f76d53SAlp Dener     if (badstep || powell || periodic) {
20892f76d53SAlp Dener       if (qn->monflg) {
2095ba6227bSPeter Brune         ierr = PetscViewerASCIIAddTab(qn->monitor,((PetscObject)snes)->tablevel+2);CHKERRQ(ierr);
2106bdcc836SBarry Smith         if (powell) {
2116bdcc836SBarry Smith           ierr = PetscViewerASCIIPrintf(qn->monitor, "Powell restart! |%14.12e| > %6.4f*|%14.12e| i_r = %D\n", (double)PetscRealPart(DolddotD), (double)qn->powell_gamma, (double)PetscRealPart(DolddotDold),i_r);CHKERRQ(ierr);
2126bdcc836SBarry Smith         } else {
2136bdcc836SBarry Smith           ierr = PetscViewerASCIIPrintf(qn->monitor, "Periodic restart! i_r = %D\n", i_r);CHKERRQ(ierr);
2146bdcc836SBarry Smith         }
2155ba6227bSPeter Brune         ierr = PetscViewerASCIISubtractTab(qn->monitor,((PetscObject)snes)->tablevel+2);CHKERRQ(ierr);
2165ba6227bSPeter Brune       }
2175ba6227bSPeter Brune       i_r = -1;
2180c777b0cSPeter Brune       if (qn->scale_type == SNES_QN_SCALE_JACOBIAN) {
219d1e9a80fSBarry Smith         ierr = SNESComputeJacobian(snes,X,snes->jacobian,snes->jacobian_pre);CHKERRQ(ierr);
22007b62357SFande Kong         SNESCheckJacobianDomainerror(snes);
2210ecc9e1dSPeter Brune       }
22292f76d53SAlp Dener       ierr = MatLMVMReset(qn->B, PETSC_FALSE);CHKERRQ(ierr);
2230ecc9e1dSPeter Brune     }
2245ba6227bSPeter Brune   }
2254b11644fSPeter Brune   if (i == snes->max_its) {
2267d3de750SJacob Faibussowitsch     ierr = PetscInfo(snes, "Maximum number of iterations has been reached: %D\n", snes->max_its);CHKERRQ(ierr);
2274b11644fSPeter Brune     if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
2284b11644fSPeter Brune   }
2294b11644fSPeter Brune   PetscFunctionReturn(0);
2304b11644fSPeter Brune }
2314b11644fSPeter Brune 
2324b11644fSPeter Brune static PetscErrorCode SNESSetUp_QN(SNES snes)
2334b11644fSPeter Brune {
2349f83bee8SJed Brown   SNES_QN        *qn = (SNES_QN*)snes->data;
2354b11644fSPeter Brune   PetscErrorCode ierr;
236fced5a79SAsbjørn Nilsen Riseth   DM             dm;
23792f76d53SAlp Dener   PetscInt       n, N;
238335fb975SPeter Brune 
2394b11644fSPeter Brune   PetscFunctionBegin;
240fced5a79SAsbjørn Nilsen Riseth 
241fced5a79SAsbjørn Nilsen Riseth   if (!snes->vec_sol) {
242fced5a79SAsbjørn Nilsen Riseth     ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr);
243fced5a79SAsbjørn Nilsen Riseth     ierr = DMCreateGlobalVector(dm,&snes->vec_sol);CHKERRQ(ierr);
244fced5a79SAsbjørn Nilsen Riseth   }
245fa0ddf94SBarry Smith   ierr = SNESSetWorkVecs(snes,4);CHKERRQ(ierr);
24692f76d53SAlp Dener 
24792f76d53SAlp Dener   if (qn->scale_type == SNES_QN_SCALE_JACOBIAN) {
24892f76d53SAlp Dener     ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
24992f76d53SAlp Dener   }
25092f76d53SAlp Dener   if (snes->npcside== PC_LEFT && snes->functype == SNES_FUNCTION_DEFAULT) {snes->functype = SNES_FUNCTION_UNPRECONDITIONED;}
25192f76d53SAlp Dener 
25260c08b40SPeter Brune   /* set method defaults */
2531efc8c45SPeter Brune   if (qn->scale_type == SNES_QN_SCALE_DEFAULT) {
25460c08b40SPeter Brune     if (qn->type == SNES_QN_BADBROYDEN) {
25560c08b40SPeter Brune       qn->scale_type = SNES_QN_SCALE_NONE;
25660c08b40SPeter Brune     } else {
25792f76d53SAlp Dener       qn->scale_type = SNES_QN_SCALE_SCALAR;
25860c08b40SPeter Brune     }
25960c08b40SPeter Brune   }
2601efc8c45SPeter Brune   if (qn->restart_type == SNES_QN_RESTART_DEFAULT) {
26160c08b40SPeter Brune     if (qn->type == SNES_QN_LBFGS) {
26260c08b40SPeter Brune       qn->restart_type = SNES_QN_RESTART_POWELL;
26360c08b40SPeter Brune     } else {
26460c08b40SPeter Brune       qn->restart_type = SNES_QN_RESTART_PERIODIC;
26560c08b40SPeter Brune     }
26660c08b40SPeter Brune   }
26760c08b40SPeter Brune 
26892f76d53SAlp Dener   /* Set up the LMVM matrix */
26992f76d53SAlp Dener   switch (qn->type) {
27092f76d53SAlp Dener     case SNES_QN_BROYDEN:
271864588a7SAlp Dener       ierr = MatSetType(qn->B, MATLMVMBROYDEN);CHKERRQ(ierr);
27292f76d53SAlp Dener       qn->scale_type = SNES_QN_SCALE_NONE;
27392f76d53SAlp Dener       break;
27492f76d53SAlp Dener     case SNES_QN_BADBROYDEN:
275864588a7SAlp Dener       ierr = MatSetType(qn->B, MATLMVMBADBROYDEN);CHKERRQ(ierr);
27692f76d53SAlp Dener       qn->scale_type = SNES_QN_SCALE_NONE;
27792f76d53SAlp Dener       break;
27892f76d53SAlp Dener     default:
27992f76d53SAlp Dener       ierr = MatSetType(qn->B, MATLMVMBFGS);CHKERRQ(ierr);
28092f76d53SAlp Dener       switch (qn->scale_type) {
28192f76d53SAlp Dener         case SNES_QN_SCALE_NONE:
282864588a7SAlp Dener           ierr = MatLMVMSymBroydenSetScaleType(qn->B, MAT_LMVM_SYMBROYDEN_SCALE_NONE);CHKERRQ(ierr);
28392f76d53SAlp Dener           break;
28492f76d53SAlp Dener         case SNES_QN_SCALE_SCALAR:
285864588a7SAlp Dener           ierr = MatLMVMSymBroydenSetScaleType(qn->B, MAT_LMVM_SYMBROYDEN_SCALE_SCALAR);CHKERRQ(ierr);
28692f76d53SAlp Dener           break;
28792f76d53SAlp Dener         case SNES_QN_SCALE_JACOBIAN:
288864588a7SAlp Dener           ierr = MatLMVMSymBroydenSetScaleType(qn->B, MAT_LMVM_SYMBROYDEN_SCALE_USER);CHKERRQ(ierr);
28992f76d53SAlp Dener           break;
29092f76d53SAlp Dener         case SNES_QN_SCALE_DIAGONAL:
29192f76d53SAlp Dener         case SNES_QN_SCALE_DEFAULT:
29292f76d53SAlp Dener         default:
29392f76d53SAlp Dener           break;
2948e231d97SPeter Brune       }
29592f76d53SAlp Dener       break;
29692f76d53SAlp Dener   }
29792f76d53SAlp Dener   ierr = VecGetLocalSize(snes->vec_sol, &n);CHKERRQ(ierr);
29892f76d53SAlp Dener   ierr = VecGetSize(snes->vec_sol, &N);CHKERRQ(ierr);
29992f76d53SAlp Dener   ierr = MatSetSizes(qn->B, n, n, N, N);CHKERRQ(ierr);
30092f76d53SAlp Dener   ierr = MatSetUp(qn->B);CHKERRQ(ierr);
30192f76d53SAlp Dener   ierr = MatLMVMReset(qn->B, PETSC_TRUE);CHKERRQ(ierr);
30292f76d53SAlp Dener   ierr = MatLMVMSetHistorySize(qn->B, qn->m);CHKERRQ(ierr);
30392f76d53SAlp Dener   ierr = MatLMVMAllocate(qn->B, snes->vec_sol, snes->vec_func);CHKERRQ(ierr);
3044b11644fSPeter Brune   PetscFunctionReturn(0);
3054b11644fSPeter Brune }
3064b11644fSPeter Brune 
3074b11644fSPeter Brune static PetscErrorCode SNESReset_QN(SNES snes)
3084b11644fSPeter Brune {
3094b11644fSPeter Brune   PetscErrorCode ierr;
3109f83bee8SJed Brown   SNES_QN        *qn;
3110adebc6cSBarry Smith 
3124b11644fSPeter Brune   PetscFunctionBegin;
3134b11644fSPeter Brune   if (snes->data) {
3149f83bee8SJed Brown     qn = (SNES_QN*)snes->data;
31592f76d53SAlp Dener     ierr = MatDestroy(&qn->B);CHKERRQ(ierr);
3164b11644fSPeter Brune   }
3174b11644fSPeter Brune   PetscFunctionReturn(0);
3184b11644fSPeter Brune }
3194b11644fSPeter Brune 
3204b11644fSPeter Brune static PetscErrorCode SNESDestroy_QN(SNES snes)
3214b11644fSPeter Brune {
3224b11644fSPeter Brune   PetscErrorCode ierr;
3236e111a19SKarl Rupp 
3244b11644fSPeter Brune   PetscFunctionBegin;
3254b11644fSPeter Brune   ierr = SNESReset_QN(snes);CHKERRQ(ierr);
3264b11644fSPeter Brune   ierr = PetscFree(snes->data);CHKERRQ(ierr);
327bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)snes,"",NULL);CHKERRQ(ierr);
3284b11644fSPeter Brune   PetscFunctionReturn(0);
3294b11644fSPeter Brune }
3304b11644fSPeter Brune 
3314416b707SBarry Smith static PetscErrorCode SNESSetFromOptions_QN(PetscOptionItems *PetscOptionsObject,SNES snes)
3324b11644fSPeter Brune {
3334b11644fSPeter Brune 
3344b11644fSPeter Brune   PetscErrorCode    ierr;
3352150357eSBarry Smith   SNES_QN           *qn    = (SNES_QN*)snes->data;
33692f76d53SAlp Dener   PetscBool         flg;
337f1c6b773SPeter Brune   SNESLineSearch    linesearch;
3382150357eSBarry Smith   SNESQNRestartType rtype = qn->restart_type;
3392150357eSBarry Smith   SNESQNScaleType   stype = qn->scale_type;
3401efc8c45SPeter Brune   SNESQNType        qtype = qn->type;
3412150357eSBarry Smith 
3424b11644fSPeter Brune   PetscFunctionBegin;
343e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"SNES QN options");CHKERRQ(ierr);
3440298fd71SBarry Smith   ierr = PetscOptionsInt("-snes_qn_m","Number of past states saved for L-BFGS methods","SNESQN",qn->m,&qn->m,NULL);CHKERRQ(ierr);
3450298fd71SBarry Smith   ierr = PetscOptionsReal("-snes_qn_powell_gamma","Powell angle tolerance",          "SNESQN", qn->powell_gamma, &qn->powell_gamma, NULL);CHKERRQ(ierr);
34692f76d53SAlp Dener   ierr = PetscOptionsBool("-snes_qn_monitor",         "Monitor for the QN methods",      "SNESQN", qn->monflg, &qn->monflg, NULL);CHKERRQ(ierr);
34788f769c5SPeter Brune   ierr = PetscOptionsEnum("-snes_qn_scale_type","Scaling type","SNESQNSetScaleType",SNESQNScaleTypes,(PetscEnum)stype,(PetscEnum*)&stype,&flg);CHKERRQ(ierr);
34860d4fc61SSatish Balay   if (flg) {ierr = SNESQNSetScaleType(snes,stype);CHKERRQ(ierr);}
34988f769c5SPeter Brune 
35088f769c5SPeter Brune   ierr = PetscOptionsEnum("-snes_qn_restart_type","Restart type","SNESQNSetRestartType",SNESQNRestartTypes,(PetscEnum)rtype,(PetscEnum*)&rtype,&flg);CHKERRQ(ierr);
35160d4fc61SSatish Balay   if (flg) {ierr = SNESQNSetRestartType(snes,rtype);CHKERRQ(ierr);}
35288f769c5SPeter Brune 
3530fdccdaeSBarry Smith   ierr = PetscOptionsEnum("-snes_qn_type","Quasi-Newton update type","",SNESQNTypes,(PetscEnum)qtype,(PetscEnum*)&qtype,&flg);CHKERRQ(ierr);
3541efc8c45SPeter Brune   if (flg) {ierr = SNESQNSetType(snes,qtype);CHKERRQ(ierr);}
35592f76d53SAlp Dener   ierr = MatSetFromOptions(qn->B);CHKERRQ(ierr);
3564b11644fSPeter Brune   ierr = PetscOptionsTail();CHKERRQ(ierr);
3579e764e56SPeter Brune   if (!snes->linesearch) {
3587601faf0SJed Brown     ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr);
359ec786807SJed Brown     if (!((PetscObject)linesearch)->type_name) {
36060c08b40SPeter Brune       if (qn->type == SNES_QN_LBFGS) {
3611a4f838cSPeter Brune         ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHCP);CHKERRQ(ierr);
36260c08b40SPeter Brune       } else if (qn->type == SNES_QN_BROYDEN) {
36360c08b40SPeter Brune         ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHBASIC);CHKERRQ(ierr);
36460c08b40SPeter Brune       } else {
36560c08b40SPeter Brune         ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHL2);CHKERRQ(ierr);
36660c08b40SPeter Brune       }
3679e764e56SPeter Brune     }
368ec786807SJed Brown   }
36992f76d53SAlp Dener   if (qn->monflg) {
37092f76d53SAlp Dener     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &qn->monitor);CHKERRQ(ierr);
37144f7e39eSPeter Brune   }
3724b11644fSPeter Brune   PetscFunctionReturn(0);
3734b11644fSPeter Brune }
3744b11644fSPeter Brune 
3755cd83419SPeter Brune static PetscErrorCode SNESView_QN(SNES snes, PetscViewer viewer)
3765cd83419SPeter Brune {
3775cd83419SPeter Brune   SNES_QN        *qn    = (SNES_QN*)snes->data;
3785cd83419SPeter Brune   PetscBool      iascii;
3795cd83419SPeter Brune   PetscErrorCode ierr;
3805cd83419SPeter Brune 
3815cd83419SPeter Brune   PetscFunctionBegin;
3825cd83419SPeter Brune   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
3835cd83419SPeter Brune   if (iascii) {
384efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  type is %s, restart type is %s, scale type is %s\n",SNESQNTypes[qn->type],SNESQNRestartTypes[qn->restart_type],SNESQNScaleTypes[qn->scale_type]);CHKERRQ(ierr);
3856bdcc836SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Stored subspace size: %D\n", qn->m);CHKERRQ(ierr);
3865cd83419SPeter Brune   }
3875cd83419SPeter Brune   PetscFunctionReturn(0);
3885cd83419SPeter Brune }
38992c02d66SPeter Brune 
3900c777b0cSPeter Brune /*@
3910c777b0cSPeter Brune     SNESQNSetRestartType - Sets the restart type for SNESQN.
3920c777b0cSPeter Brune 
3930c777b0cSPeter Brune     Logically Collective on SNES
3940c777b0cSPeter Brune 
3950c777b0cSPeter Brune     Input Parameters:
3960c777b0cSPeter Brune +   snes - the iterative context
3970c777b0cSPeter Brune -   rtype - restart type
3980c777b0cSPeter Brune 
3990c777b0cSPeter Brune     Options Database:
4000c777b0cSPeter Brune +   -snes_qn_restart_type <powell,periodic,none> - set the restart type
40184c577daSBarry Smith -   -snes_qn_m <m> - sets the number of stored updates and the restart period for periodic
4020c777b0cSPeter Brune 
4030c777b0cSPeter Brune     Level: intermediate
4040c777b0cSPeter Brune 
4050c777b0cSPeter Brune     SNESQNRestartTypes:
4060c777b0cSPeter Brune +   SNES_QN_RESTART_NONE - never restart
4070c777b0cSPeter Brune .   SNES_QN_RESTART_POWELL - restart based upon descent criteria
4080c777b0cSPeter Brune -   SNES_QN_RESTART_PERIODIC - restart after a fixed number of iterations
4090c777b0cSPeter Brune 
4100c777b0cSPeter Brune @*/
4112150357eSBarry Smith PetscErrorCode SNESQNSetRestartType(SNES snes, SNESQNRestartType rtype)
4122150357eSBarry Smith {
4130c777b0cSPeter Brune   PetscErrorCode ierr;
4146e111a19SKarl Rupp 
4150c777b0cSPeter Brune   PetscFunctionBegin;
4160c777b0cSPeter Brune   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
4170c777b0cSPeter Brune   ierr = PetscTryMethod(snes,"SNESQNSetRestartType_C",(SNES,SNESQNRestartType),(snes,rtype));CHKERRQ(ierr);
4180c777b0cSPeter Brune   PetscFunctionReturn(0);
4190c777b0cSPeter Brune }
4200c777b0cSPeter Brune 
4210c777b0cSPeter Brune /*@
42284c577daSBarry Smith     SNESQNSetScaleType - Sets the scaling type for the inner inverse Jacobian in SNESQN.
4230c777b0cSPeter Brune 
4240c777b0cSPeter Brune     Logically Collective on SNES
4250c777b0cSPeter Brune 
4260c777b0cSPeter Brune     Input Parameters:
4270c777b0cSPeter Brune +   snes - the iterative context
4280c777b0cSPeter Brune -   stype - scale type
4290c777b0cSPeter Brune 
4300c777b0cSPeter Brune     Options Database:
43192f76d53SAlp Dener .   -snes_qn_scale_type <diagonal,none,scalar,jacobian>
4320c777b0cSPeter Brune 
4330c777b0cSPeter Brune     Level: intermediate
4340c777b0cSPeter Brune 
43584c577daSBarry Smith     SNESQNScaleTypes:
4360c777b0cSPeter Brune +   SNES_QN_SCALE_NONE - don't scale the problem
4377044b745SBarry Smith .   SNES_QN_SCALE_SCALAR - use Shanno scaling
43892f76d53SAlp Dener .   SNES_QN_SCALE_DIAGONAL - scale with a diagonalized BFGS formula (see Gilbert and Lemarechal 1989), available
439a01a0525SBarry Smith -   SNES_QN_SCALE_JACOBIAN - scale by solving a linear system coming from the Jacobian you provided with SNESSetJacobian() computed at the first iteration
440a01a0525SBarry Smith                              of QN and at ever restart.
4410c777b0cSPeter Brune 
442446c23c1SPierre Jolivet .seealso: SNES, SNESQN, SNESLineSearch, SNESQNScaleType, SNESSetJacobian()
4430c777b0cSPeter Brune @*/
4440c777b0cSPeter Brune 
4452150357eSBarry Smith PetscErrorCode SNESQNSetScaleType(SNES snes, SNESQNScaleType stype)
4462150357eSBarry Smith {
4470c777b0cSPeter Brune   PetscErrorCode ierr;
4486e111a19SKarl Rupp 
4490c777b0cSPeter Brune   PetscFunctionBegin;
4500c777b0cSPeter Brune   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
4510c777b0cSPeter Brune   ierr = PetscTryMethod(snes,"SNESQNSetScaleType_C",(SNES,SNESQNScaleType),(snes,stype));CHKERRQ(ierr);
4520c777b0cSPeter Brune   PetscFunctionReturn(0);
4530c777b0cSPeter Brune }
4540c777b0cSPeter Brune 
4550adebc6cSBarry Smith PetscErrorCode SNESQNSetScaleType_QN(SNES snes, SNESQNScaleType stype)
4560adebc6cSBarry Smith {
4570c777b0cSPeter Brune   SNES_QN *qn = (SNES_QN*)snes->data;
4586e111a19SKarl Rupp 
4590c777b0cSPeter Brune   PetscFunctionBegin;
4600c777b0cSPeter Brune   qn->scale_type = stype;
4617044b745SBarry Smith   if (stype == SNES_QN_SCALE_JACOBIAN) snes->usesksp = PETSC_TRUE;
4620c777b0cSPeter Brune   PetscFunctionReturn(0);
4630c777b0cSPeter Brune }
4640c777b0cSPeter Brune 
4650adebc6cSBarry Smith PetscErrorCode SNESQNSetRestartType_QN(SNES snes, SNESQNRestartType rtype)
4660adebc6cSBarry Smith {
4670c777b0cSPeter Brune   SNES_QN *qn = (SNES_QN*)snes->data;
4686e111a19SKarl Rupp 
4690c777b0cSPeter Brune   PetscFunctionBegin;
4700c777b0cSPeter Brune   qn->restart_type = rtype;
4710c777b0cSPeter Brune   PetscFunctionReturn(0);
4720c777b0cSPeter Brune }
4730c777b0cSPeter Brune 
4741efc8c45SPeter Brune /*@
4751efc8c45SPeter Brune     SNESQNSetType - Sets the quasi-Newton variant to be used in SNESQN.
4761efc8c45SPeter Brune 
4771efc8c45SPeter Brune     Logically Collective on SNES
4781efc8c45SPeter Brune 
4791efc8c45SPeter Brune     Input Parameters:
4801efc8c45SPeter Brune +   snes - the iterative context
4811efc8c45SPeter Brune -   qtype - variant type
4821efc8c45SPeter Brune 
4831efc8c45SPeter Brune     Options Database:
48484c577daSBarry Smith .   -snes_qn_type <lbfgs,broyden,badbroyden>
4851efc8c45SPeter Brune 
4861efc8c45SPeter Brune     Level: beginner
4871efc8c45SPeter Brune 
4881efc8c45SPeter Brune     SNESQNTypes:
4891efc8c45SPeter Brune +   SNES_QN_LBFGS - LBFGS variant
4901efc8c45SPeter Brune .   SNES_QN_BROYDEN - Broyden variant
4911efc8c45SPeter Brune -   SNES_QN_BADBROYDEN - Bad Broyden variant
4921efc8c45SPeter Brune 
4931efc8c45SPeter Brune @*/
4941efc8c45SPeter Brune 
4951efc8c45SPeter Brune PetscErrorCode SNESQNSetType(SNES snes, SNESQNType qtype)
4961efc8c45SPeter Brune {
4971efc8c45SPeter Brune   PetscErrorCode ierr;
4981efc8c45SPeter Brune 
4991efc8c45SPeter Brune   PetscFunctionBegin;
5001efc8c45SPeter Brune   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
5011efc8c45SPeter Brune   ierr = PetscTryMethod(snes,"SNESQNSetType_C",(SNES,SNESQNType),(snes,qtype));CHKERRQ(ierr);
5021efc8c45SPeter Brune   PetscFunctionReturn(0);
5031efc8c45SPeter Brune }
5041efc8c45SPeter Brune 
5051efc8c45SPeter Brune PetscErrorCode SNESQNSetType_QN(SNES snes, SNESQNType qtype)
5061efc8c45SPeter Brune {
5071efc8c45SPeter Brune   SNES_QN *qn = (SNES_QN*)snes->data;
5081efc8c45SPeter Brune 
5091efc8c45SPeter Brune   PetscFunctionBegin;
5101efc8c45SPeter Brune   qn->type = qtype;
5111efc8c45SPeter Brune   PetscFunctionReturn(0);
5121efc8c45SPeter Brune }
5131efc8c45SPeter Brune 
5144b11644fSPeter Brune /* -------------------------------------------------------------------------- */
5154b11644fSPeter Brune /*MC
5164b11644fSPeter Brune       SNESQN - Limited-Memory Quasi-Newton methods for the solution of nonlinear systems.
5174b11644fSPeter Brune 
5186cc8130cSPeter Brune       Options Database:
5196cc8130cSPeter Brune 
52084c577daSBarry Smith +     -snes_qn_m <m> - Number of past states saved for the L-Broyden methods.
52184c577daSBarry Smith +     -snes_qn_restart_type <powell,periodic,none> - set the restart type
5226bdcc836SBarry Smith .     -snes_qn_powell_gamma - Angle condition for restart.
5231867fe5bSPeter Brune .     -snes_qn_powell_descent - Descent condition for restart.
52484c577daSBarry Smith .     -snes_qn_type <lbfgs,broyden,badbroyden> - QN type
52592f76d53SAlp Dener .     -snes_qn_scale_type <diagonal,none,scalar,jacobian> - scaling performed on inner Jacobian
52672835e02SPeter Brune .     -snes_linesearch_type <cp, l2, basic> - Type of line search.
52784c577daSBarry Smith -     -snes_qn_monitor - Monitors the quasi-newton Jacobian.
5286cc8130cSPeter Brune 
52995452b02SPatrick Sanan       Notes:
53095452b02SPatrick Sanan     This implements the L-BFGS, Broyden, and "Bad" Broyden algorithms for the solution of F(x) = b using
531b8840d6bSPeter Brune       previous change in F(x) and x to form the approximate inverse Jacobian using a series of multiplicative rank-one
532b8840d6bSPeter Brune       updates.
5336cc8130cSPeter Brune 
5341867fe5bSPeter Brune       When using a nonlinear preconditioner, one has two options as to how the preconditioner is applied.  The first of
5351867fe5bSPeter Brune       these options, sequential, uses the preconditioner to generate a new solution and function and uses those at this
53684c577daSBarry Smith       iteration as the current iteration's values when constructing the approximate Jacobian.  The second, composed,
53784c577daSBarry Smith       perturbs the problem the Jacobian represents to be P(x, b) - x = 0, where P(x, b) is the preconditioner.
5381867fe5bSPeter Brune 
5392d547940SBarry Smith       Uses left nonlinear preconditioning by default.
5402d547940SBarry Smith 
5416cc8130cSPeter Brune       References:
54296a0c994SBarry Smith +   1. -   Kelley, C.T., Iterative Methods for Linear and Nonlinear Equations, Chapter 8, SIAM, 1995.
54396a0c994SBarry Smith .   2. -   R. Byrd, J. Nocedal, R. Schnabel, Representations of Quasi Newton Matrices and their use in Limited Memory Methods,
5440a8e8854SPeter Brune       Technical Report, Northwestern University, June 1992.
54596a0c994SBarry Smith .   3. -   Peter N. Brown, Alan C. Hindmarsh, Homer F. Walker, Experiments with Quasi-Newton Methods in Solving Stiff ODE
5460a8e8854SPeter Brune       Systems, SIAM J. Sci. Stat. Comput. Vol 6(2), April 1985.
54792f76d53SAlp Dener .   4. -   Peter R. Brune, Matthew G. Knepley, Barry F. Smith, and Xuemin Tu, "Composing Scalable Nonlinear Algebraic Solvers",
5484f02bc6aSBarry Smith        SIAM Review, 57(4), 2015
54992f76d53SAlp Dener .   5. -   Griewank, Andreas. "Broyden updating, the good and the bad!." Doc. Math (2012): 301-315.
550110fc3b0SBarry Smith .   6. -   Gilbert, Jean Charles, and Claude Lemar{\'e}chal. "Some numerical experiments with variable-storage quasi-Newton algorithms."
55192f76d53SAlp Dener       Mathematical programming 45.1-3 (1989): 407-435.
55292f76d53SAlp Dener -   7. -   Dener A., Munson T. "Accelerating Limited-Memory Quasi-Newton Convergence for Large-Scale Optimization"
553110fc3b0SBarry Smith       Computational Science - ICCS 2019. ICCS 2019. Lecture Notes in Computer Science, vol 11538. Springer, Cham
5544b11644fSPeter Brune 
5554b11644fSPeter Brune       Level: beginner
5564b11644fSPeter Brune 
55704d7464bSBarry Smith .seealso:  SNESCreate(), SNES, SNESSetType(), SNESNEWTONLS, SNESNEWTONTR
5586cc8130cSPeter Brune 
5594b11644fSPeter Brune M*/
5608cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESCreate_QN(SNES snes)
5614b11644fSPeter Brune {
5624b11644fSPeter Brune   PetscErrorCode ierr;
5639f83bee8SJed Brown   SNES_QN        *qn;
56492f76d53SAlp Dener   const char     *optionsprefix;
5654b11644fSPeter Brune 
5664b11644fSPeter Brune   PetscFunctionBegin;
5674b11644fSPeter Brune   snes->ops->setup          = SNESSetUp_QN;
5684b11644fSPeter Brune   snes->ops->solve          = SNESSolve_QN;
5694b11644fSPeter Brune   snes->ops->destroy        = SNESDestroy_QN;
5704b11644fSPeter Brune   snes->ops->setfromoptions = SNESSetFromOptions_QN;
5715cd83419SPeter Brune   snes->ops->view           = SNESView_QN;
5724b11644fSPeter Brune   snes->ops->reset          = SNESReset_QN;
5734b11644fSPeter Brune 
574efd4aadfSBarry Smith   snes->npcside= PC_LEFT;
57547f26062SPeter Brune 
576efd4aadfSBarry Smith   snes->usesnpc = PETSC_TRUE;
57742f4f86dSBarry Smith   snes->usesksp = PETSC_FALSE;
57842f4f86dSBarry Smith 
5794fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_TRUE;
5804fc747eaSLawrence Mitchell 
58188976e71SPeter Brune   if (!snes->tolerancesset) {
5820e444f03SPeter Brune     snes->max_funcs = 30000;
5830e444f03SPeter Brune     snes->max_its   = 10000;
58488976e71SPeter Brune   }
5850e444f03SPeter Brune 
586b00a9115SJed Brown   ierr                = PetscNewLog(snes,&qn);CHKERRQ(ierr);
5874b11644fSPeter Brune   snes->data          = (void*) qn;
5880ecc9e1dSPeter Brune   qn->m               = 10;
589b21d5a53SPeter Brune   qn->scaling         = 1.0;
5900298fd71SBarry Smith   qn->monitor         = NULL;
59192f76d53SAlp Dener   qn->monflg          = PETSC_FALSE;
592b8840d6bSPeter Brune   qn->powell_gamma    = 0.9999;
59360c08b40SPeter Brune   qn->scale_type      = SNES_QN_SCALE_DEFAULT;
59460c08b40SPeter Brune   qn->restart_type    = SNES_QN_RESTART_DEFAULT;
595b8840d6bSPeter Brune   qn->type            = SNES_QN_LBFGS;
596ea630c6eSPeter Brune 
59792f76d53SAlp Dener   ierr = MatCreate(PetscObjectComm((PetscObject)snes), &qn->B);CHKERRQ(ierr);
59892f76d53SAlp Dener   ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr);
59992f76d53SAlp Dener   ierr = MatSetOptionsPrefix(qn->B, optionsprefix);CHKERRQ(ierr);
60092f76d53SAlp Dener 
601bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESQNSetScaleType_C",SNESQNSetScaleType_QN);CHKERRQ(ierr);
602bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESQNSetRestartType_C",SNESQNSetRestartType_QN);CHKERRQ(ierr);
6031efc8c45SPeter Brune   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESQNSetType_C",SNESQNSetType_QN);CHKERRQ(ierr);
6044b11644fSPeter Brune   PetscFunctionReturn(0);
6054b11644fSPeter Brune }
606