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 6*92f76d53SAlp Dener const char *const SNESQNScaleTypes[] = {"DEFAULT","NONE","SCALAR","DIAGONAL","JACOBIAN","SNESQNScaleType","SNES_QN_SCALING_",0}; 71efc8c45SPeter Brune const char *const SNESQNRestartTypes[] = {"DEFAULT","NONE","POWELL","PERIODIC","SNESQNRestartType","SNES_QN_RESTART_",0}; 860c08b40SPeter Brune const char *const SNESQNTypes[] = {"LBFGS","BROYDEN","BADBROYDEN","SNESQNType","SNES_QN_",0}; 9b8840d6bSPeter Brune 104b11644fSPeter Brune typedef struct { 11*92f76d53SAlp 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 */ 14*92f76d53SAlp 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; 33*92f76d53SAlp 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; 406c4ed002SBarry Smith if (snes->xl || snes->xu || snes->ops->computevariablebounds) SETERRQ1(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); 120*92f76d53SAlp 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++) { 124*92f76d53SAlp Dener /* update QN approx and calculate step */ 125*92f76d53SAlp Dener ierr = MatLMVMUpdate(qn->B, X, D);CHKERRQ(ierr); 126*92f76d53SAlp Dener ierr = MatSolve(qn->B, D, Y);CHKERRQ(ierr); 127*92f76d53SAlp 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); 136*92f76d53SAlp 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 } 142*92f76d53SAlp Dener badstep = PETSC_TRUE; 1430ecc9e1dSPeter Brune } 1443af51624SPeter Brune 14588d374b2SPeter Brune /* convergence monitoring */ 146b21d5a53SPeter Brune ierr = PetscInfo4(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); 167*92f76d53SAlp 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 187*92f76d53SAlp 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. */ 207*92f76d53SAlp Dener if (badstep || powell || periodic) { 208*92f76d53SAlp 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 } 222*92f76d53SAlp Dener ierr = MatLMVMReset(qn->B, PETSC_FALSE);CHKERRQ(ierr); 2230ecc9e1dSPeter Brune } 2245ba6227bSPeter Brune } 2254b11644fSPeter Brune if (i == snes->max_its) { 2264b11644fSPeter Brune ierr = PetscInfo1(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; 237*92f76d53SAlp 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); 246*92f76d53SAlp Dener 247*92f76d53SAlp Dener if (qn->scale_type == SNES_QN_SCALE_JACOBIAN) { 248*92f76d53SAlp Dener ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr); 249*92f76d53SAlp Dener } 250*92f76d53SAlp Dener if (snes->npcside== PC_LEFT && snes->functype == SNES_FUNCTION_DEFAULT) {snes->functype = SNES_FUNCTION_UNPRECONDITIONED;} 251*92f76d53SAlp 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 { 257*92f76d53SAlp 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 268*92f76d53SAlp Dener /* Set up the LMVM matrix */ 269*92f76d53SAlp Dener switch (qn->type) { 270*92f76d53SAlp Dener case SNES_QN_BROYDEN: 271*92f76d53SAlp Dener ierr = MatSetType(qn->B, MATLMVMBRDN);CHKERRQ(ierr); 272*92f76d53SAlp Dener qn->scale_type = SNES_QN_SCALE_NONE; 273*92f76d53SAlp Dener break; 274*92f76d53SAlp Dener case SNES_QN_BADBROYDEN: 275*92f76d53SAlp Dener ierr = MatSetType(qn->B, MATLMVMBADBRDN);CHKERRQ(ierr); 276*92f76d53SAlp Dener qn->scale_type = SNES_QN_SCALE_NONE; 277*92f76d53SAlp Dener break; 278*92f76d53SAlp Dener default: 279*92f76d53SAlp Dener ierr = MatSetType(qn->B, MATLMVMBFGS);CHKERRQ(ierr); 280*92f76d53SAlp Dener switch (qn->scale_type) { 281*92f76d53SAlp Dener case SNES_QN_SCALE_NONE: 282*92f76d53SAlp Dener ierr = MatSymBrdnSetScaleType(qn->B, MAT_LMVM_SYMBRDN_SCALE_NONE);CHKERRQ(ierr); 283*92f76d53SAlp Dener break; 284*92f76d53SAlp Dener case SNES_QN_SCALE_SCALAR: 285*92f76d53SAlp Dener ierr = MatSymBrdnSetScaleType(qn->B, MAT_LMVM_SYMBRDN_SCALE_SCALAR);CHKERRQ(ierr); 286*92f76d53SAlp Dener break; 287*92f76d53SAlp Dener case SNES_QN_SCALE_JACOBIAN: 288*92f76d53SAlp Dener ierr = MatSymBrdnSetScaleType(qn->B, MAT_LMVM_SYMBRDN_SCALE_USER);CHKERRQ(ierr); 289*92f76d53SAlp Dener break; 290*92f76d53SAlp Dener case SNES_QN_SCALE_DIAGONAL: 291*92f76d53SAlp Dener case SNES_QN_SCALE_DEFAULT: 292*92f76d53SAlp Dener default: 293*92f76d53SAlp Dener break; 2948e231d97SPeter Brune } 295*92f76d53SAlp Dener break; 296*92f76d53SAlp Dener } 297*92f76d53SAlp Dener ierr = VecGetLocalSize(snes->vec_sol, &n);CHKERRQ(ierr); 298*92f76d53SAlp Dener ierr = VecGetSize(snes->vec_sol, &N);CHKERRQ(ierr); 299*92f76d53SAlp Dener ierr = MatSetSizes(qn->B, n, n, N, N);CHKERRQ(ierr); 300*92f76d53SAlp Dener ierr = MatSetUp(qn->B);CHKERRQ(ierr); 301*92f76d53SAlp Dener ierr = MatLMVMReset(qn->B, PETSC_TRUE);CHKERRQ(ierr); 302*92f76d53SAlp Dener ierr = MatLMVMSetHistorySize(qn->B, qn->m);CHKERRQ(ierr); 303*92f76d53SAlp 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; 315*92f76d53SAlp 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; 336*92f76d53SAlp 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); 346*92f76d53SAlp 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); 34888f769c5SPeter Brune 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); 35188f769c5SPeter Brune 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);} 355*92f76d53SAlp 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); 35960c08b40SPeter Brune if (qn->type == SNES_QN_LBFGS) { 3601a4f838cSPeter Brune ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHCP);CHKERRQ(ierr); 36160c08b40SPeter Brune } else if (qn->type == SNES_QN_BROYDEN) { 36260c08b40SPeter Brune ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHBASIC);CHKERRQ(ierr); 36360c08b40SPeter Brune } else { 36460c08b40SPeter Brune ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHL2);CHKERRQ(ierr); 36560c08b40SPeter Brune } 3669e764e56SPeter Brune } 367*92f76d53SAlp Dener if (qn->monflg) { 368*92f76d53SAlp Dener ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &qn->monitor);CHKERRQ(ierr); 36944f7e39eSPeter Brune } 3704b11644fSPeter Brune PetscFunctionReturn(0); 3714b11644fSPeter Brune } 3724b11644fSPeter Brune 3735cd83419SPeter Brune static PetscErrorCode SNESView_QN(SNES snes, PetscViewer viewer) 3745cd83419SPeter Brune { 3755cd83419SPeter Brune SNES_QN *qn = (SNES_QN*)snes->data; 3765cd83419SPeter Brune PetscBool iascii; 3775cd83419SPeter Brune PetscErrorCode ierr; 3785cd83419SPeter Brune 3795cd83419SPeter Brune PetscFunctionBegin; 3805cd83419SPeter Brune ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 3815cd83419SPeter Brune if (iascii) { 382efd4aadfSBarry 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); 3836bdcc836SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Stored subspace size: %D\n", qn->m);CHKERRQ(ierr); 3845cd83419SPeter Brune } 3855cd83419SPeter Brune PetscFunctionReturn(0); 3865cd83419SPeter Brune } 38792c02d66SPeter Brune 3880c777b0cSPeter Brune /*@ 3890c777b0cSPeter Brune SNESQNSetRestartType - Sets the restart type for SNESQN. 3900c777b0cSPeter Brune 3910c777b0cSPeter Brune Logically Collective on SNES 3920c777b0cSPeter Brune 3930c777b0cSPeter Brune Input Parameters: 3940c777b0cSPeter Brune + snes - the iterative context 3950c777b0cSPeter Brune - rtype - restart type 3960c777b0cSPeter Brune 3970c777b0cSPeter Brune Options Database: 3980c777b0cSPeter Brune + -snes_qn_restart_type <powell,periodic,none> - set the restart type 39984c577daSBarry Smith - -snes_qn_m <m> - sets the number of stored updates and the restart period for periodic 4000c777b0cSPeter Brune 4010c777b0cSPeter Brune Level: intermediate 4020c777b0cSPeter Brune 4030c777b0cSPeter Brune SNESQNRestartTypes: 4040c777b0cSPeter Brune + SNES_QN_RESTART_NONE - never restart 4050c777b0cSPeter Brune . SNES_QN_RESTART_POWELL - restart based upon descent criteria 4060c777b0cSPeter Brune - SNES_QN_RESTART_PERIODIC - restart after a fixed number of iterations 4070c777b0cSPeter Brune 4080c777b0cSPeter Brune @*/ 4092150357eSBarry Smith PetscErrorCode SNESQNSetRestartType(SNES snes, SNESQNRestartType rtype) 4102150357eSBarry Smith { 4110c777b0cSPeter Brune PetscErrorCode ierr; 4126e111a19SKarl Rupp 4130c777b0cSPeter Brune PetscFunctionBegin; 4140c777b0cSPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4150c777b0cSPeter Brune ierr = PetscTryMethod(snes,"SNESQNSetRestartType_C",(SNES,SNESQNRestartType),(snes,rtype));CHKERRQ(ierr); 4160c777b0cSPeter Brune PetscFunctionReturn(0); 4170c777b0cSPeter Brune } 4180c777b0cSPeter Brune 4190c777b0cSPeter Brune /*@ 42084c577daSBarry Smith SNESQNSetScaleType - Sets the scaling type for the inner inverse Jacobian in SNESQN. 4210c777b0cSPeter Brune 4220c777b0cSPeter Brune Logically Collective on SNES 4230c777b0cSPeter Brune 4240c777b0cSPeter Brune Input Parameters: 4250c777b0cSPeter Brune + snes - the iterative context 4260c777b0cSPeter Brune - stype - scale type 4270c777b0cSPeter Brune 4280c777b0cSPeter Brune Options Database: 429*92f76d53SAlp Dener . -snes_qn_scale_type <diagonal,none,scalar,jacobian> 4300c777b0cSPeter Brune 4310c777b0cSPeter Brune Level: intermediate 4320c777b0cSPeter Brune 43384c577daSBarry Smith SNESQNScaleTypes: 4340c777b0cSPeter Brune + SNES_QN_SCALE_NONE - don't scale the problem 435*92f76d53SAlp Dener . SNES_QN_SCALE_SCALAR - use shanno scaling 436*92f76d53SAlp Dener . SNES_QN_SCALE_DIAGONAL - scale with a diagonalized BFGS formula (see Gilbert and Lemarechal 1989), available 437a01a0525SBarry Smith - SNES_QN_SCALE_JACOBIAN - scale by solving a linear system coming from the Jacobian you provided with SNESSetJacobian() computed at the first iteration 438a01a0525SBarry Smith of QN and at ever restart. 4390c777b0cSPeter Brune 440a01a0525SBarry Smith .seealso: SNES, SNESQN, SNESLineSearch, SNESQNScaleType, SNESetJacobian() 4410c777b0cSPeter Brune @*/ 4420c777b0cSPeter Brune 4432150357eSBarry Smith PetscErrorCode SNESQNSetScaleType(SNES snes, SNESQNScaleType stype) 4442150357eSBarry Smith { 4450c777b0cSPeter Brune PetscErrorCode ierr; 4466e111a19SKarl Rupp 4470c777b0cSPeter Brune PetscFunctionBegin; 4480c777b0cSPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4490c777b0cSPeter Brune ierr = PetscTryMethod(snes,"SNESQNSetScaleType_C",(SNES,SNESQNScaleType),(snes,stype));CHKERRQ(ierr); 4500c777b0cSPeter Brune PetscFunctionReturn(0); 4510c777b0cSPeter Brune } 4520c777b0cSPeter Brune 4530adebc6cSBarry Smith PetscErrorCode SNESQNSetScaleType_QN(SNES snes, SNESQNScaleType stype) 4540adebc6cSBarry Smith { 4550c777b0cSPeter Brune SNES_QN *qn = (SNES_QN*)snes->data; 4566e111a19SKarl Rupp 4570c777b0cSPeter Brune PetscFunctionBegin; 4580c777b0cSPeter Brune qn->scale_type = stype; 4590c777b0cSPeter Brune PetscFunctionReturn(0); 4600c777b0cSPeter Brune } 4610c777b0cSPeter Brune 4620adebc6cSBarry Smith PetscErrorCode SNESQNSetRestartType_QN(SNES snes, SNESQNRestartType rtype) 4630adebc6cSBarry Smith { 4640c777b0cSPeter Brune SNES_QN *qn = (SNES_QN*)snes->data; 4656e111a19SKarl Rupp 4660c777b0cSPeter Brune PetscFunctionBegin; 4670c777b0cSPeter Brune qn->restart_type = rtype; 4680c777b0cSPeter Brune PetscFunctionReturn(0); 4690c777b0cSPeter Brune } 4700c777b0cSPeter Brune 4711efc8c45SPeter Brune /*@ 4721efc8c45SPeter Brune SNESQNSetType - Sets the quasi-Newton variant to be used in SNESQN. 4731efc8c45SPeter Brune 4741efc8c45SPeter Brune Logically Collective on SNES 4751efc8c45SPeter Brune 4761efc8c45SPeter Brune Input Parameters: 4771efc8c45SPeter Brune + snes - the iterative context 4781efc8c45SPeter Brune - qtype - variant type 4791efc8c45SPeter Brune 4801efc8c45SPeter Brune Options Database: 48184c577daSBarry Smith . -snes_qn_type <lbfgs,broyden,badbroyden> 4821efc8c45SPeter Brune 4831efc8c45SPeter Brune Level: beginner 4841efc8c45SPeter Brune 4851efc8c45SPeter Brune SNESQNTypes: 4861efc8c45SPeter Brune + SNES_QN_LBFGS - LBFGS variant 4871efc8c45SPeter Brune . SNES_QN_BROYDEN - Broyden variant 4881efc8c45SPeter Brune - SNES_QN_BADBROYDEN - Bad Broyden variant 4891efc8c45SPeter Brune 4901efc8c45SPeter Brune @*/ 4911efc8c45SPeter Brune 4921efc8c45SPeter Brune PetscErrorCode SNESQNSetType(SNES snes, SNESQNType qtype) 4931efc8c45SPeter Brune { 4941efc8c45SPeter Brune PetscErrorCode ierr; 4951efc8c45SPeter Brune 4961efc8c45SPeter Brune PetscFunctionBegin; 4971efc8c45SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4981efc8c45SPeter Brune ierr = PetscTryMethod(snes,"SNESQNSetType_C",(SNES,SNESQNType),(snes,qtype));CHKERRQ(ierr); 4991efc8c45SPeter Brune PetscFunctionReturn(0); 5001efc8c45SPeter Brune } 5011efc8c45SPeter Brune 5021efc8c45SPeter Brune PetscErrorCode SNESQNSetType_QN(SNES snes, SNESQNType qtype) 5031efc8c45SPeter Brune { 5041efc8c45SPeter Brune SNES_QN *qn = (SNES_QN*)snes->data; 5051efc8c45SPeter Brune 5061efc8c45SPeter Brune PetscFunctionBegin; 5071efc8c45SPeter Brune qn->type = qtype; 5081efc8c45SPeter Brune PetscFunctionReturn(0); 5091efc8c45SPeter Brune } 5101efc8c45SPeter Brune 5114b11644fSPeter Brune /* -------------------------------------------------------------------------- */ 5124b11644fSPeter Brune /*MC 5134b11644fSPeter Brune SNESQN - Limited-Memory Quasi-Newton methods for the solution of nonlinear systems. 5144b11644fSPeter Brune 5156cc8130cSPeter Brune Options Database: 5166cc8130cSPeter Brune 51784c577daSBarry Smith + -snes_qn_m <m> - Number of past states saved for the L-Broyden methods. 51884c577daSBarry Smith + -snes_qn_restart_type <powell,periodic,none> - set the restart type 5196bdcc836SBarry Smith . -snes_qn_powell_gamma - Angle condition for restart. 5201867fe5bSPeter Brune . -snes_qn_powell_descent - Descent condition for restart. 52184c577daSBarry Smith . -snes_qn_type <lbfgs,broyden,badbroyden> - QN type 522*92f76d53SAlp Dener . -snes_qn_scale_type <diagonal,none,scalar,jacobian> - scaling performed on inner Jacobian 52372835e02SPeter Brune . -snes_linesearch_type <cp, l2, basic> - Type of line search. 52484c577daSBarry Smith - -snes_qn_monitor - Monitors the quasi-newton Jacobian. 5256cc8130cSPeter Brune 52695452b02SPatrick Sanan Notes: 52795452b02SPatrick Sanan This implements the L-BFGS, Broyden, and "Bad" Broyden algorithms for the solution of F(x) = b using 528b8840d6bSPeter Brune previous change in F(x) and x to form the approximate inverse Jacobian using a series of multiplicative rank-one 529b8840d6bSPeter Brune updates. 5306cc8130cSPeter Brune 5311867fe5bSPeter Brune When using a nonlinear preconditioner, one has two options as to how the preconditioner is applied. The first of 5321867fe5bSPeter Brune these options, sequential, uses the preconditioner to generate a new solution and function and uses those at this 53384c577daSBarry Smith iteration as the current iteration's values when constructing the approximate Jacobian. The second, composed, 53484c577daSBarry Smith perturbs the problem the Jacobian represents to be P(x, b) - x = 0, where P(x, b) is the preconditioner. 5351867fe5bSPeter Brune 5362d547940SBarry Smith Uses left nonlinear preconditioning by default. 5372d547940SBarry Smith 5386cc8130cSPeter Brune References: 53996a0c994SBarry Smith + 1. - Kelley, C.T., Iterative Methods for Linear and Nonlinear Equations, Chapter 8, SIAM, 1995. 54096a0c994SBarry Smith . 2. - R. Byrd, J. Nocedal, R. Schnabel, Representations of Quasi Newton Matrices and their use in Limited Memory Methods, 5410a8e8854SPeter Brune Technical Report, Northwestern University, June 1992. 54296a0c994SBarry Smith . 3. - Peter N. Brown, Alan C. Hindmarsh, Homer F. Walker, Experiments with Quasi-Newton Methods in Solving Stiff ODE 5430a8e8854SPeter Brune Systems, SIAM J. Sci. Stat. Comput. Vol 6(2), April 1985. 544*92f76d53SAlp Dener . 4. - Peter R. Brune, Matthew G. Knepley, Barry F. Smith, and Xuemin Tu, "Composing Scalable Nonlinear Algebraic Solvers", 5454f02bc6aSBarry Smith SIAM Review, 57(4), 2015 546*92f76d53SAlp Dener . 5. - Griewank, Andreas. "Broyden updating, the good and the bad!." Doc. Math (2012): 301-315. 547*92f76d53SAlp Dener . 6. - Gilbert, Jean Charles, and Claude Lemaréchal. "Some numerical experiments with variable-storage quasi-Newton algorithms." 548*92f76d53SAlp Dener Mathematical programming 45.1-3 (1989): 407-435. 549*92f76d53SAlp Dener - 7. - Dener A., Munson T. "Accelerating Limited-Memory Quasi-Newton Convergence for Large-Scale Optimization" 550*92f76d53SAlp Dener Computational Science – ICCS 2019. ICCS 2019. Lecture Notes in Computer Science, vol 11538. Springer, Cham 5514b11644fSPeter Brune 5524b11644fSPeter Brune Level: beginner 5534b11644fSPeter Brune 55404d7464bSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESNEWTONLS, SNESNEWTONTR 5556cc8130cSPeter Brune 5564b11644fSPeter Brune M*/ 5578cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESCreate_QN(SNES snes) 5584b11644fSPeter Brune { 5594b11644fSPeter Brune PetscErrorCode ierr; 5609f83bee8SJed Brown SNES_QN *qn; 561*92f76d53SAlp Dener const char *optionsprefix; 5624b11644fSPeter Brune 5634b11644fSPeter Brune PetscFunctionBegin; 5644b11644fSPeter Brune snes->ops->setup = SNESSetUp_QN; 5654b11644fSPeter Brune snes->ops->solve = SNESSolve_QN; 5664b11644fSPeter Brune snes->ops->destroy = SNESDestroy_QN; 5674b11644fSPeter Brune snes->ops->setfromoptions = SNESSetFromOptions_QN; 5685cd83419SPeter Brune snes->ops->view = SNESView_QN; 5694b11644fSPeter Brune snes->ops->reset = SNESReset_QN; 5704b11644fSPeter Brune 571efd4aadfSBarry Smith snes->npcside= PC_LEFT; 57247f26062SPeter Brune 573efd4aadfSBarry Smith snes->usesnpc = PETSC_TRUE; 57442f4f86dSBarry Smith snes->usesksp = PETSC_FALSE; 57542f4f86dSBarry Smith 5764fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_TRUE; 5774fc747eaSLawrence Mitchell 57888976e71SPeter Brune if (!snes->tolerancesset) { 5790e444f03SPeter Brune snes->max_funcs = 30000; 5800e444f03SPeter Brune snes->max_its = 10000; 58188976e71SPeter Brune } 5820e444f03SPeter Brune 583b00a9115SJed Brown ierr = PetscNewLog(snes,&qn);CHKERRQ(ierr); 5844b11644fSPeter Brune snes->data = (void*) qn; 5850ecc9e1dSPeter Brune qn->m = 10; 586b21d5a53SPeter Brune qn->scaling = 1.0; 5870298fd71SBarry Smith qn->monitor = NULL; 588*92f76d53SAlp Dener qn->monflg = PETSC_FALSE; 589b8840d6bSPeter Brune qn->powell_gamma = 0.9999; 59060c08b40SPeter Brune qn->scale_type = SNES_QN_SCALE_DEFAULT; 59160c08b40SPeter Brune qn->restart_type = SNES_QN_RESTART_DEFAULT; 592b8840d6bSPeter Brune qn->type = SNES_QN_LBFGS; 593ea630c6eSPeter Brune 594*92f76d53SAlp Dener ierr = MatCreate(PetscObjectComm((PetscObject)snes), &qn->B);CHKERRQ(ierr); 595*92f76d53SAlp Dener ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr); 596*92f76d53SAlp Dener ierr = MatSetOptionsPrefix(qn->B, optionsprefix);CHKERRQ(ierr); 597*92f76d53SAlp Dener 598bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESQNSetScaleType_C",SNESQNSetScaleType_QN);CHKERRQ(ierr); 599bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESQNSetRestartType_C",SNESQNSetRestartType_QN);CHKERRQ(ierr); 6001efc8c45SPeter Brune ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESQNSetType_C",SNESQNSetType_QN);CHKERRQ(ierr); 6014b11644fSPeter Brune PetscFunctionReturn(0); 6024b11644fSPeter Brune } 603