10c777b0cSPeter Brune #include <petsc-private/snesimpl.h> /*I "petscsnes.h" I*/ 24b11644fSPeter Brune 38e231d97SPeter Brune #define H(i,j) qn->dXdFmat[i*qn->m + j] 48e231d97SPeter Brune 56a6fc655SJed Brown const char *const SNESQNScaleTypes[] = {"NONE","SHANNO","LINESEARCH","JACOBIAN","SNESQNScaleType","SNES_QN_SCALING_",0}; 66a6fc655SJed Brown const char *const SNESQNRestartTypes[] = {"NONE","POWELL","PERIODIC","SNESQNRestartType","SNES_QN_RESTART_",0}; 7*60c08b40SPeter Brune const char *const SNESQNTypes[] = {"LBFGS","BROYDEN","BADBROYDEN","SNESQNType","SNES_QN_",0}; 8b8840d6bSPeter Brune 9b8840d6bSPeter Brune typedef enum {SNES_QN_LBFGS = 0, 10b8840d6bSPeter Brune SNES_QN_BROYDEN = 1, 110ad7597dSKarl Rupp SNES_QN_BADBROYDEN = 2 120ad7597dSKarl Rupp } SNESQNType; 136bf1b2e5SPeter Brune 144b11644fSPeter Brune typedef struct { 15b8840d6bSPeter Brune Vec *U; /* Stored past states (vary from method to method) */ 16b8840d6bSPeter Brune Vec *V; /* Stored past states (vary from method to method) */ 178e231d97SPeter Brune PetscInt m; /* The number of kept previous steps */ 185c7a0a03SPeter Brune PetscReal *lambda; /* The line search history of the method */ 195c7a0a03SPeter Brune PetscReal *norm; /* norms of the steps */ 208e231d97SPeter Brune PetscScalar *alpha, *beta; 218e231d97SPeter Brune PetscScalar *dXtdF, *dFtdX, *YtdX; 2218aa0c0cSPeter Brune PetscBool singlereduction; /* Aggregated reduction implementation */ 238e231d97SPeter Brune PetscScalar *dXdFmat; /* A matrix of values for dX_i dot dF_j */ 2444f7e39eSPeter Brune PetscViewer monitor; 256bf1b2e5SPeter Brune PetscReal powell_gamma; /* Powell angle restart condition */ 266bf1b2e5SPeter Brune PetscReal powell_downhill; /* Powell descent restart condition */ 27b21d5a53SPeter Brune PetscReal scaling; /* scaling of H0 */ 28b8840d6bSPeter Brune SNESQNType type; /* the type of quasi-newton method used */ 2988f769c5SPeter Brune SNESQNScaleType scale_type; /* the type of scaling used */ 300c777b0cSPeter Brune SNESQNRestartType restart_type; /* determine the frequency and type of restart conditions */ 319f83bee8SJed Brown } SNES_QN; 324b11644fSPeter Brune 334b11644fSPeter Brune #undef __FUNCT__ 34b8840d6bSPeter Brune #define __FUNCT__ "SNESQNApply_Broyden" 355051edb1SPeter Brune PetscErrorCode SNESQNApply_Broyden(SNES snes,PetscInt it,Vec Y,Vec X,Vec Xold,Vec D) 362150357eSBarry Smith { 374b11644fSPeter Brune PetscErrorCode ierr; 389f83bee8SJed Brown SNES_QN *qn = (SNES_QN*)snes->data; 39b8840d6bSPeter Brune Vec W = snes->work[3]; 40b8840d6bSPeter Brune Vec *U = qn->U; 41b8840d6bSPeter Brune KSPConvergedReason kspreason; 42b8840d6bSPeter Brune PetscInt m = qn->m; 435c7a0a03SPeter Brune PetscInt k,i,j,lits,l = m; 445c7a0a03SPeter Brune PetscReal unorm,a,b; 455c7a0a03SPeter Brune PetscReal *lambda=qn->lambda; 46b8840d6bSPeter Brune PetscScalar gdot; 4759e7931aSPeter Brune PetscReal udot; 482150357eSBarry Smith 49b8840d6bSPeter Brune PetscFunctionBegin; 50b8840d6bSPeter Brune if (it < m) l = it; 515c7a0a03SPeter Brune if (it > 0) { 525c7a0a03SPeter Brune k = (it-1)%l; 535c7a0a03SPeter Brune ierr = SNESLineSearchGetLambda(snes->linesearch,&lambda[k]);CHKERRQ(ierr); 54a49fa0d8SPeter Brune ierr = VecCopy(Xold,U[k]);CHKERRQ(ierr); 555051edb1SPeter Brune ierr = VecAXPY(U[k],-1.0,X);CHKERRQ(ierr); 565c7a0a03SPeter Brune if (qn->monitor) { 575c7a0a03SPeter Brune ierr = PetscViewerASCIIAddTab(qn->monitor,((PetscObject)snes)->tablevel+2);CHKERRQ(ierr); 585c7a0a03SPeter Brune ierr = PetscViewerASCIIPrintf(qn->monitor, "scaling vector %d of %d by lambda: %14.12e \n",k,l,lambda[k]);CHKERRQ(ierr); 595c7a0a03SPeter Brune ierr = PetscViewerASCIISubtractTab(qn->monitor,((PetscObject)snes)->tablevel+2);CHKERRQ(ierr); 605c7a0a03SPeter Brune } 615c7a0a03SPeter Brune } 62b8840d6bSPeter Brune if (qn->scale_type == SNES_QN_SCALE_JACOBIAN) { 63d4211eb9SBarry Smith ierr = KSPSolve(snes->ksp,D,W);CHKERRQ(ierr); 64b8840d6bSPeter Brune ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 65b8840d6bSPeter Brune if (kspreason < 0) { 66b8840d6bSPeter Brune if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 67b8840d6bSPeter Brune ierr = PetscInfo2(snes,"iter=%D, number linear solve failures %D greater than current SNES allowed, stopping solve\n",snes->iter,snes->numLinearSolveFailures);CHKERRQ(ierr); 68b8840d6bSPeter Brune snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 69b8840d6bSPeter Brune PetscFunctionReturn(0); 70b8840d6bSPeter Brune } 71b8840d6bSPeter Brune } 72b8840d6bSPeter Brune ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 73b8840d6bSPeter Brune snes->linear_its += lits; 74b8840d6bSPeter Brune ierr = VecCopy(W,Y);CHKERRQ(ierr); 75b8840d6bSPeter Brune } else { 76b8840d6bSPeter Brune ierr = VecCopy(D,Y);CHKERRQ(ierr); 77b8840d6bSPeter Brune ierr = VecScale(Y,qn->scaling);CHKERRQ(ierr); 78b8840d6bSPeter Brune } 79b8840d6bSPeter Brune 80b8840d6bSPeter Brune /* inward recursion starting at the first update and working forward */ 81b8840d6bSPeter Brune for (i = 0; i < l-1; i++) { 825c7a0a03SPeter Brune j = (it+i-l)%l; 835c7a0a03SPeter Brune k = (it+i-l+1)%l; 845c7a0a03SPeter Brune ierr = VecNorm(U[j],NORM_2,&unorm);CHKERRQ(ierr); 855c7a0a03SPeter Brune ierr = VecDot(U[j],Y,&gdot);CHKERRQ(ierr); 8659e7931aSPeter Brune unorm *= unorm; 8759e7931aSPeter Brune udot = PetscRealPart(gdot); 885c7a0a03SPeter Brune a = (lambda[j]/lambda[k]); 895c7a0a03SPeter Brune b = -(1.-lambda[j]); 9059e7931aSPeter Brune a *= udot/unorm; 9159e7931aSPeter Brune b *= udot/unorm; 925c7a0a03SPeter Brune ierr = VecAXPBYPCZ(Y,a,b,1.,U[k],U[j]);CHKERRQ(ierr); 935c7a0a03SPeter Brune 94b8840d6bSPeter Brune if (qn->monitor) { 95b8840d6bSPeter Brune ierr = PetscViewerASCIIAddTab(qn->monitor,((PetscObject)snes)->tablevel+2);CHKERRQ(ierr); 965c7a0a03SPeter Brune ierr = PetscViewerASCIIPrintf(qn->monitor, "using vector %d and %d, gdot: %14.12e\n",k,j,gdot);CHKERRQ(ierr); 97b8840d6bSPeter Brune ierr = PetscViewerASCIISubtractTab(qn->monitor,((PetscObject)snes)->tablevel+2);CHKERRQ(ierr); 98b8840d6bSPeter Brune } 99b8840d6bSPeter Brune } 100b8840d6bSPeter Brune if (l > 0) { 101b8840d6bSPeter Brune k = (it-1)%l; 102b8840d6bSPeter Brune ierr = VecDot(U[k],Y,&gdot);CHKERRQ(ierr); 1035c7a0a03SPeter Brune ierr = VecNorm(U[k],NORM_2,&unorm);CHKERRQ(ierr); 10459e7931aSPeter Brune unorm *= unorm; 10559e7931aSPeter Brune udot = PetscRealPart(gdot); 10659e7931aSPeter Brune a = unorm/(unorm-lambda[k]*udot); 10759e7931aSPeter Brune b = -(1.-lambda[k])*udot/(unorm-lambda[k]*udot); 108b8840d6bSPeter Brune if (qn->monitor) { 109b8840d6bSPeter Brune ierr = PetscViewerASCIIAddTab(qn->monitor,((PetscObject)snes)->tablevel+2);CHKERRQ(ierr); 11059e7931aSPeter Brune ierr = PetscViewerASCIIPrintf(qn->monitor, "using vector %d: a: %14.12e b: %14.12e \n",k,a,b);CHKERRQ(ierr); 111b8840d6bSPeter Brune ierr = PetscViewerASCIISubtractTab(qn->monitor,((PetscObject)snes)->tablevel+2);CHKERRQ(ierr); 112b8840d6bSPeter Brune } 1135c7a0a03SPeter Brune ierr = VecAXPBY(Y,b,a,U[k]);CHKERRQ(ierr); 114b8840d6bSPeter Brune } 1155c7a0a03SPeter Brune l = m; 1165c7a0a03SPeter Brune if (it+1<m)l=it+1; 1175c7a0a03SPeter Brune k = it%l; 1185c7a0a03SPeter Brune if (qn->monitor) { 1195c7a0a03SPeter Brune ierr = PetscViewerASCIIAddTab(qn->monitor,((PetscObject)snes)->tablevel+2);CHKERRQ(ierr); 1205c7a0a03SPeter Brune ierr = PetscViewerASCIIPrintf(qn->monitor, "setting vector %d of %d\n",k,l);CHKERRQ(ierr); 1215c7a0a03SPeter Brune ierr = PetscViewerASCIISubtractTab(qn->monitor,((PetscObject)snes)->tablevel+2);CHKERRQ(ierr); 1225c7a0a03SPeter Brune } 123b8840d6bSPeter Brune PetscFunctionReturn(0); 124b8840d6bSPeter Brune } 125b8840d6bSPeter Brune 126b8840d6bSPeter Brune #undef __FUNCT__ 127b8840d6bSPeter Brune #define __FUNCT__ "SNESQNApply_BadBroyden" 1280adebc6cSBarry Smith PetscErrorCode SNESQNApply_BadBroyden(SNES snes,PetscInt it,Vec Y,Vec X,Vec Xold,Vec D,Vec Dold) 1290adebc6cSBarry Smith { 130b8840d6bSPeter Brune PetscErrorCode ierr; 131b8840d6bSPeter Brune SNES_QN *qn = (SNES_QN*)snes->data; 132b8840d6bSPeter Brune Vec W = snes->work[3]; 133b8840d6bSPeter Brune Vec *U = qn->U; 134b8840d6bSPeter Brune Vec *T = qn->V; 135b8840d6bSPeter Brune 136b8840d6bSPeter Brune /* ksp thing for jacobian scaling */ 137b8840d6bSPeter Brune KSPConvergedReason kspreason; 138c9e59058SPeter Brune PetscInt h,k,j,i,lits; 139b8840d6bSPeter Brune PetscInt m = qn->m; 1405051edb1SPeter Brune PetscScalar gdot,udot; 141b8840d6bSPeter Brune PetscInt l = m; 1420adebc6cSBarry Smith 143b8840d6bSPeter Brune PetscFunctionBegin; 144b8840d6bSPeter Brune if (it < m) l = it; 145b8840d6bSPeter Brune ierr = VecCopy(D,Y);CHKERRQ(ierr); 146b8840d6bSPeter Brune if (l > 0) { 147b8840d6bSPeter Brune k = (it-1)%l; 148c9e59058SPeter Brune ierr = SNESLineSearchGetLambda(snes->linesearch,&qn->lambda[k]);CHKERRQ(ierr); 149b8840d6bSPeter Brune ierr = VecCopy(Dold,U[k]);CHKERRQ(ierr); 150b8840d6bSPeter Brune ierr = VecAXPY(U[k],-1.0,D);CHKERRQ(ierr); 1515051edb1SPeter Brune ierr = VecCopy(Xold,T[k]);CHKERRQ(ierr); 1525051edb1SPeter Brune ierr = VecAXPY(T[k],-1.0,X);CHKERRQ(ierr); 153b8840d6bSPeter Brune } 154b8840d6bSPeter Brune 155b8840d6bSPeter Brune if (qn->scale_type == SNES_QN_SCALE_JACOBIAN) { 156d4211eb9SBarry Smith ierr = KSPSolve(snes->ksp,Y,W);CHKERRQ(ierr); 157b8840d6bSPeter Brune ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 158b8840d6bSPeter Brune if (kspreason < 0) { 159b8840d6bSPeter Brune if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 160b8840d6bSPeter Brune ierr = PetscInfo2(snes,"iter=%D, number linear solve failures %D greater than current SNES allowed, stopping solve\n",snes->iter,snes->numLinearSolveFailures);CHKERRQ(ierr); 161b8840d6bSPeter Brune snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 162b8840d6bSPeter Brune PetscFunctionReturn(0); 163b8840d6bSPeter Brune } 164b8840d6bSPeter Brune } 165b8840d6bSPeter Brune ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 166b8840d6bSPeter Brune snes->linear_its += lits; 167b8840d6bSPeter Brune ierr = VecCopy(W,Y);CHKERRQ(ierr); 168b8840d6bSPeter Brune } else { 169b8840d6bSPeter Brune ierr = VecScale(Y,qn->scaling);CHKERRQ(ierr); 170b8840d6bSPeter Brune } 1715051edb1SPeter Brune 1725051edb1SPeter Brune /* inward recursion starting at the first update and working forward */ 1735051edb1SPeter Brune if (l > 0) { 1745051edb1SPeter Brune for (i = 0; i < l-1; i++) { 175c9e59058SPeter Brune j = (it+i-l)%l; 176c9e59058SPeter Brune k = (it+i-l+1)%l; 177c9e59058SPeter Brune h = (it-1)%l; 178c9e59058SPeter Brune ierr = VecDotBegin(U[j],U[h],&gdot);CHKERRQ(ierr); 179c9e59058SPeter Brune ierr = VecDotBegin(U[j],U[j],&udot);CHKERRQ(ierr); 180c9e59058SPeter Brune ierr = VecDotEnd(U[j],U[h],&gdot);CHKERRQ(ierr); 181c9e59058SPeter Brune ierr = VecDotEnd(U[j],U[j],&udot);CHKERRQ(ierr); 1825051edb1SPeter Brune ierr = VecAXPY(Y,PetscRealPart(gdot)/PetscRealPart(udot),T[k]);CHKERRQ(ierr); 183c9e59058SPeter Brune ierr = VecAXPY(Y,-(1.-qn->lambda[k])*PetscRealPart(gdot)/PetscRealPart(udot),T[j]);CHKERRQ(ierr); 1845051edb1SPeter Brune if (qn->monitor) { 1855051edb1SPeter Brune ierr = PetscViewerASCIIAddTab(qn->monitor,((PetscObject)snes)->tablevel+2);CHKERRQ(ierr); 1865051edb1SPeter Brune ierr = PetscViewerASCIIPrintf(qn->monitor, "it: %d k: %d gdot: %14.12e\n", it, k, PetscRealPart(gdot));CHKERRQ(ierr); 1875051edb1SPeter Brune ierr = PetscViewerASCIISubtractTab(qn->monitor,((PetscObject)snes)->tablevel+2);CHKERRQ(ierr); 1885051edb1SPeter Brune } 1895051edb1SPeter Brune } 1905051edb1SPeter Brune } 191b8840d6bSPeter Brune PetscFunctionReturn(0); 192b8840d6bSPeter Brune } 193b8840d6bSPeter Brune 194b8840d6bSPeter Brune #undef __FUNCT__ 195b8840d6bSPeter Brune #define __FUNCT__ "SNESQNApply_LBFGS" 1960adebc6cSBarry Smith PetscErrorCode SNESQNApply_LBFGS(SNES snes,PetscInt it,Vec Y,Vec X,Vec Xold,Vec D,Vec Dold) 1970adebc6cSBarry Smith { 198b8840d6bSPeter Brune PetscErrorCode ierr; 199b8840d6bSPeter Brune SNES_QN *qn = (SNES_QN*)snes->data; 200b8840d6bSPeter Brune Vec W = snes->work[3]; 201b8840d6bSPeter Brune Vec *dX = qn->U; 202b8840d6bSPeter Brune Vec *dF = qn->V; 203bd052dfeSPeter Brune PetscScalar *alpha = qn->alpha; 204bd052dfeSPeter Brune PetscScalar *beta = qn->beta; 2058e231d97SPeter Brune PetscScalar *dXtdF = qn->dXtdF; 206b8840d6bSPeter Brune PetscScalar *dFtdX = qn->dFtdX; 2078e231d97SPeter Brune PetscScalar *YtdX = qn->YtdX; 208bd052dfeSPeter Brune 2090ecc9e1dSPeter Brune /* ksp thing for jacobian scaling */ 2100ecc9e1dSPeter Brune KSPConvergedReason kspreason; 2118e231d97SPeter Brune PetscInt k,i,j,g,lits; 2124b11644fSPeter Brune PetscInt m = qn->m; 2134b11644fSPeter Brune PetscScalar t; 2144b11644fSPeter Brune PetscInt l = m; 2158e231d97SPeter Brune 2164b11644fSPeter Brune PetscFunctionBegin; 2175ba6227bSPeter Brune if (it < m) l = it; 2181c6523dcSPeter Brune ierr = VecCopy(D,Y);CHKERRQ(ierr); 219b8840d6bSPeter Brune if (it > 0) { 220b8840d6bSPeter Brune k = (it - 1) % l; 221b8840d6bSPeter Brune ierr = VecCopy(D,dF[k]);CHKERRQ(ierr); 222b8840d6bSPeter Brune ierr = VecAXPY(dF[k], -1.0, Dold);CHKERRQ(ierr); 223b8840d6bSPeter Brune ierr = VecCopy(X, dX[k]);CHKERRQ(ierr); 224b8840d6bSPeter Brune ierr = VecAXPY(dX[k], -1.0, Xold);CHKERRQ(ierr); 22518aa0c0cSPeter Brune if (qn->singlereduction) { 2261c6523dcSPeter Brune ierr = VecMDotBegin(dF[k],l,dX,dXtdF);CHKERRQ(ierr); 2271c6523dcSPeter Brune ierr = VecMDotBegin(dX[k],l,dF,dFtdX);CHKERRQ(ierr); 2281c6523dcSPeter Brune ierr = VecMDotBegin(Y,l,dX,YtdX);CHKERRQ(ierr); 2291c6523dcSPeter Brune ierr = VecMDotEnd(dF[k],l,dX,dXtdF);CHKERRQ(ierr); 2301c6523dcSPeter Brune ierr = VecMDotEnd(dX[k],l,dF,dFtdX);CHKERRQ(ierr); 2311c6523dcSPeter Brune ierr = VecMDotEnd(Y,l,dX,YtdX);CHKERRQ(ierr); 232b8840d6bSPeter Brune for (j = 0; j < l; j++) { 233b8840d6bSPeter Brune H(k, j) = dFtdX[j]; 234b8840d6bSPeter Brune H(j, k) = dXtdF[j]; 235b8840d6bSPeter Brune } 236b8840d6bSPeter Brune /* copy back over to make the computation of alpha and beta easier */ 2371aa26658SKarl Rupp for (j = 0; j < l; j++) dXtdF[j] = H(j, j); 238b8840d6bSPeter Brune } else { 239b8840d6bSPeter Brune ierr = VecDot(dX[k], dF[k], &dXtdF[k]);CHKERRQ(ierr); 24023d44fbcSPeter Brune } 24123d44fbcSPeter Brune if (qn->scale_type == SNES_QN_SCALE_LINESEARCH) { 242b8840d6bSPeter Brune ierr = SNESLineSearchGetLambda(snes->linesearch,&qn->scaling);CHKERRQ(ierr); 243b8840d6bSPeter Brune } 244b8840d6bSPeter Brune } 245b8840d6bSPeter Brune 2464b11644fSPeter Brune /* outward recursion starting at iteration k's update and working back */ 2474b11644fSPeter Brune for (i=0; i<l; i++) { 248b21d5a53SPeter Brune k = (it-i-1)%l; 24918aa0c0cSPeter Brune if (qn->singlereduction) { 2508e231d97SPeter Brune /* construct t = dX[k] dot Y as Y_0 dot dX[k] + sum(-alpha[j]dX[k]dF[j]) */ 2518e231d97SPeter Brune t = YtdX[k]; 2528e231d97SPeter Brune for (j=0; j<i; j++) { 2538e231d97SPeter Brune g = (it-j-1)%l; 254b3cfccb2SPeter Brune t -= alpha[g]*H(k, g); 2558e231d97SPeter Brune } 2568e231d97SPeter Brune alpha[k] = t/H(k,k); 2578e231d97SPeter Brune } else { 2583af51624SPeter Brune ierr = VecDot(dX[k],Y,&t);CHKERRQ(ierr); 2598e231d97SPeter Brune alpha[k] = t/dXtdF[k]; 2608e231d97SPeter Brune } 26144f7e39eSPeter Brune if (qn->monitor) { 2623af51624SPeter Brune ierr = PetscViewerASCIIAddTab(qn->monitor,((PetscObject)snes)->tablevel+2);CHKERRQ(ierr); 2635ba6227bSPeter Brune ierr = PetscViewerASCIIPrintf(qn->monitor, "it: %d k: %d alpha: %14.12e\n", it, k, PetscRealPart(alpha[k]));CHKERRQ(ierr); 2643af51624SPeter Brune ierr = PetscViewerASCIISubtractTab(qn->monitor,((PetscObject)snes)->tablevel+2);CHKERRQ(ierr); 26544f7e39eSPeter Brune } 2666bf1b2e5SPeter Brune ierr = VecAXPY(Y,-alpha[k],dF[k]);CHKERRQ(ierr); 2674b11644fSPeter Brune } 2684b11644fSPeter Brune 2690c777b0cSPeter Brune if (qn->scale_type == SNES_QN_SCALE_JACOBIAN) { 270d4211eb9SBarry Smith ierr = KSPSolve(snes->ksp,Y,W);CHKERRQ(ierr); 2710ecc9e1dSPeter Brune ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr); 2720ecc9e1dSPeter Brune if (kspreason < 0) { 2730ecc9e1dSPeter Brune if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) { 2740ecc9e1dSPeter Brune ierr = PetscInfo2(snes,"iter=%D, number linear solve failures %D greater than current SNES allowed, stopping solve\n",snes->iter,snes->numLinearSolveFailures);CHKERRQ(ierr); 2750ecc9e1dSPeter Brune snes->reason = SNES_DIVERGED_LINEAR_SOLVE; 2760ecc9e1dSPeter Brune PetscFunctionReturn(0); 2770ecc9e1dSPeter Brune } 2780ecc9e1dSPeter Brune } 2790ecc9e1dSPeter Brune ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); 2800ecc9e1dSPeter Brune snes->linear_its += lits; 281b8840d6bSPeter Brune ierr = VecCopy(W, Y);CHKERRQ(ierr); 2820ecc9e1dSPeter Brune } else { 283b21d5a53SPeter Brune ierr = VecScale(Y, qn->scaling);CHKERRQ(ierr); 2840ecc9e1dSPeter Brune } 28518aa0c0cSPeter Brune if (qn->singlereduction) { 286b8840d6bSPeter Brune ierr = VecMDot(Y,l,dF,YtdX);CHKERRQ(ierr); 2878e231d97SPeter Brune } 2884b11644fSPeter Brune /* inward recursion starting at the first update and working forward */ 289bd052dfeSPeter Brune for (i = 0; i < l; i++) { 290b21d5a53SPeter Brune k = (it + i - l) % l; 29118aa0c0cSPeter Brune if (qn->singlereduction) { 2928e231d97SPeter Brune t = YtdX[k]; 2938e231d97SPeter Brune for (j = 0; j < i; j++) { 2948e231d97SPeter Brune g = (it + j - l) % l; 295b3cfccb2SPeter Brune t += (alpha[g] - beta[g])*H(g, k); 2968e231d97SPeter Brune } 2978e231d97SPeter Brune beta[k] = t / H(k, k); 2988e231d97SPeter Brune } else { 2996bf1b2e5SPeter Brune ierr = VecDot(dF[k], Y, &t);CHKERRQ(ierr); 3008e231d97SPeter Brune beta[k] = t / dXtdF[k]; 3018e231d97SPeter Brune } 30222d28d08SBarry Smith ierr = VecAXPY(Y, (alpha[k] - beta[k]), dX[k]);CHKERRQ(ierr); 30344f7e39eSPeter Brune if (qn->monitor) { 3043af51624SPeter Brune ierr = PetscViewerASCIIAddTab(qn->monitor,((PetscObject)snes)->tablevel+2);CHKERRQ(ierr); 3055ba6227bSPeter Brune ierr = PetscViewerASCIIPrintf(qn->monitor, "it: %d k: %d alpha - beta: %14.12e\n", it, k, PetscRealPart(alpha[k] - beta[k]));CHKERRQ(ierr); 3063af51624SPeter Brune ierr = PetscViewerASCIISubtractTab(qn->monitor,((PetscObject)snes)->tablevel+2);CHKERRQ(ierr); 30744f7e39eSPeter Brune } 3084b11644fSPeter Brune } 3094b11644fSPeter Brune PetscFunctionReturn(0); 3104b11644fSPeter Brune } 3114b11644fSPeter Brune 3124b11644fSPeter Brune #undef __FUNCT__ 3134b11644fSPeter Brune #define __FUNCT__ "SNESSolve_QN" 3144b11644fSPeter Brune static PetscErrorCode SNESSolve_QN(SNES snes) 3154b11644fSPeter Brune { 3164b11644fSPeter Brune PetscErrorCode ierr; 3179f83bee8SJed Brown SNES_QN *qn = (SNES_QN*) snes->data; 31815f5eeeaSPeter Brune Vec X,Xold; 3190a3905e1SPeter Brune Vec F,W; 32047f26062SPeter Brune Vec Y,D,Dold; 321b8840d6bSPeter Brune PetscInt i, i_r; 322335fb975SPeter Brune PetscReal fnorm,xnorm,ynorm,gnorm; 3230c777b0cSPeter Brune PetscBool lssucceed,powell,periodic; 3241c6523dcSPeter Brune PetscScalar DolddotD,DolddotDold; 3250ecc9e1dSPeter Brune MatStructure flg = DIFFERENT_NONZERO_PATTERN; 326b7281c8aSPeter Brune SNESConvergedReason reason; 3270ecc9e1dSPeter Brune 3284b11644fSPeter Brune /* basically just a regular newton's method except for the application of the jacobian */ 3294b11644fSPeter Brune 3306e111a19SKarl Rupp PetscFunctionBegin; 3319f3a0142SPeter Brune F = snes->vec_func; /* residual vector */ 3323af51624SPeter Brune Y = snes->vec_sol_update; /* search direction generated by J^-1D*/ 3330a3905e1SPeter Brune W = snes->work[3]; 334b8840d6bSPeter Brune X = snes->vec_sol; /* solution vector */ 335335fb975SPeter Brune Xold = snes->work[0]; 3363af51624SPeter Brune 3373af51624SPeter Brune /* directions generated by the preconditioned problem with F_pre = F or x - M(x, b) */ 338335fb975SPeter Brune D = snes->work[1]; 339335fb975SPeter Brune Dold = snes->work[2]; 3404b11644fSPeter Brune 3414b11644fSPeter Brune snes->reason = SNES_CONVERGED_ITERATING; 3424b11644fSPeter Brune 343ce8c27fbSBarry Smith ierr = PetscObjectAMSTakeAccess((PetscObject)snes);CHKERRQ(ierr); 3444b11644fSPeter Brune snes->iter = 0; 3454b11644fSPeter Brune snes->norm = 0.; 346ce8c27fbSBarry Smith ierr = PetscObjectAMSGrantAccess((PetscObject)snes);CHKERRQ(ierr); 34747f26062SPeter Brune 348b28a06ddSPeter Brune if (snes->pc && snes->pcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) { 34947f26062SPeter Brune ierr = SNESApplyPC(snes,X,NULL,NULL,F);CHKERRQ(ierr); 350b7281c8aSPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 351b7281c8aSPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 352b7281c8aSPeter Brune snes->reason = SNES_DIVERGED_INNER; 353b7281c8aSPeter Brune PetscFunctionReturn(0); 354b7281c8aSPeter Brune } 35547f26062SPeter Brune ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); 35647f26062SPeter Brune } else { 357e4ed7901SPeter Brune if (!snes->vec_func_init_set) { 35815f5eeeaSPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 3594b11644fSPeter Brune if (snes->domainerror) { 3604b11644fSPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 3614b11644fSPeter Brune PetscFunctionReturn(0); 3624b11644fSPeter Brune } 3631aa26658SKarl Rupp } else snes->vec_func_init_set = PETSC_FALSE; 364c1c75074SPeter Brune 36547f26062SPeter Brune ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); 366189a9710SBarry Smith if (PetscIsInfOrNanReal(fnorm)) { 367189a9710SBarry Smith snes->reason = SNES_DIVERGED_FNORM_NAN; 368189a9710SBarry Smith PetscFunctionReturn(0); 369189a9710SBarry Smith } 37047f26062SPeter Brune } 371b28a06ddSPeter Brune if (snes->pc && snes->pcside == PC_LEFT && snes->functype == SNES_FUNCTION_UNPRECONDITIONED) { 37247f26062SPeter Brune ierr = SNESApplyPC(snes,X,F,&fnorm,D);CHKERRQ(ierr); 373b7281c8aSPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 374b7281c8aSPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 375b7281c8aSPeter Brune snes->reason = SNES_DIVERGED_INNER; 376b7281c8aSPeter Brune PetscFunctionReturn(0); 377b7281c8aSPeter Brune } 37847f26062SPeter Brune } else { 37947f26062SPeter Brune ierr = VecCopy(F,D);CHKERRQ(ierr); 38047f26062SPeter Brune } 381b28a06ddSPeter Brune 382ce8c27fbSBarry Smith ierr = PetscObjectAMSTakeAccess((PetscObject)snes);CHKERRQ(ierr); 3834b11644fSPeter Brune snes->norm = fnorm; 384ce8c27fbSBarry Smith ierr = PetscObjectAMSGrantAccess((PetscObject)snes);CHKERRQ(ierr); 385a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr); 3864b11644fSPeter Brune ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 3874b11644fSPeter Brune 3884b11644fSPeter Brune /* test convergence */ 3894b11644fSPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 3904b11644fSPeter Brune if (snes->reason) PetscFunctionReturn(0); 39170d3b23bSPeter Brune 3923cf07b75SPeter Brune if (snes->pc && snes->pcside == PC_RIGHT) { 3933cf07b75SPeter Brune ierr = PetscLogEventBegin(SNES_NPCSolve,snes->pc,X,0,0);CHKERRQ(ierr); 3943cf07b75SPeter Brune ierr = SNESSolve(snes->pc,snes->vec_rhs,X);CHKERRQ(ierr); 3953cf07b75SPeter Brune ierr = PetscLogEventEnd(SNES_NPCSolve,snes->pc,X,0,0);CHKERRQ(ierr); 396ddd40ce5SPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 397ddd40ce5SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 398ddd40ce5SPeter Brune snes->reason = SNES_DIVERGED_INNER; 399ddd40ce5SPeter Brune PetscFunctionReturn(0); 400ddd40ce5SPeter Brune } 401ddd40ce5SPeter Brune ierr = SNESGetPCFunction(snes,F,&fnorm);CHKERRQ(ierr); 4023cf07b75SPeter Brune ierr = VecCopy(F,D);CHKERRQ(ierr); 4033cf07b75SPeter Brune } 4043cf07b75SPeter Brune 405f8e15203SPeter Brune /* scale the initial update */ 4060c777b0cSPeter Brune if (qn->scale_type == SNES_QN_SCALE_JACOBIAN) { 4070ecc9e1dSPeter Brune ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 4088cba9625SJed Brown ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr); 4090ecc9e1dSPeter Brune } 4100ecc9e1dSPeter Brune 4115ba6227bSPeter Brune for (i = 0, i_r = 0; i < snes->max_its; i++, i_r++) { 4120a3905e1SPeter Brune if (qn->scale_type == SNES_QN_SCALE_SHANNO && i_r > 0) { 4130a3905e1SPeter Brune PetscScalar ff,xf; 4140a3905e1SPeter Brune ierr = VecCopy(Dold,Y);CHKERRQ(ierr); 4150a3905e1SPeter Brune ierr = VecCopy(Xold,W);CHKERRQ(ierr); 4160a3905e1SPeter Brune ierr = VecAXPY(Y,-1.0,D);CHKERRQ(ierr); 4170a3905e1SPeter Brune ierr = VecAXPY(W,-1.0,X);CHKERRQ(ierr); 4180a3905e1SPeter Brune ierr = VecDotBegin(Y,Y,&ff);CHKERRQ(ierr); 4190a3905e1SPeter Brune ierr = VecDotBegin(W,Y,&xf);CHKERRQ(ierr); 4200a3905e1SPeter Brune ierr = VecDotEnd(Y,Y,&ff);CHKERRQ(ierr); 4210a3905e1SPeter Brune ierr = VecDotEnd(W,Y,&xf);CHKERRQ(ierr); 4220a3905e1SPeter Brune qn->scaling = PetscRealPart(xf)/PetscRealPart(ff); 4230a3905e1SPeter Brune } 424b8840d6bSPeter Brune switch (qn->type) { 425b8840d6bSPeter Brune case SNES_QN_BADBROYDEN: 426b8840d6bSPeter Brune ierr = SNESQNApply_BadBroyden(snes,i_r,Y,X,Xold,D,Dold);CHKERRQ(ierr); 427b8840d6bSPeter Brune break; 428b8840d6bSPeter Brune case SNES_QN_BROYDEN: 4295051edb1SPeter Brune ierr = SNESQNApply_Broyden(snes,i_r,Y,X,Xold,D);CHKERRQ(ierr); 430b8840d6bSPeter Brune break; 431b8840d6bSPeter Brune case SNES_QN_LBFGS: 432b8840d6bSPeter Brune SNESQNApply_LBFGS(snes,i_r,Y,X,Xold,D,Dold);CHKERRQ(ierr); 433b8840d6bSPeter Brune break; 434b8840d6bSPeter Brune } 43570d3b23bSPeter Brune /* line search for lambda */ 43670d3b23bSPeter Brune ynorm = 1; gnorm = fnorm; 4370a3905e1SPeter Brune ierr = VecCopy(D, Dold);CHKERRQ(ierr); 43815f5eeeaSPeter Brune ierr = VecCopy(X, Xold);CHKERRQ(ierr); 439f1c6b773SPeter Brune ierr = SNESLineSearchApply(snes->linesearch, X, F, &fnorm, Y);CHKERRQ(ierr); 4409f3a0142SPeter Brune if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; 4419f3a0142SPeter Brune if (snes->domainerror) { 4429f3a0142SPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 4439f3a0142SPeter Brune PetscFunctionReturn(0); 4449f3a0142SPeter Brune } 445f1c6b773SPeter Brune ierr = SNESLineSearchGetSuccess(snes->linesearch, &lssucceed);CHKERRQ(ierr); 4469f3a0142SPeter Brune if (!lssucceed) { 4479f3a0142SPeter Brune if (++snes->numFailures >= snes->maxFailures) { 4489f3a0142SPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 4499f3a0142SPeter Brune break; 4509f3a0142SPeter Brune } 4519f3a0142SPeter Brune } 452f1c6b773SPeter Brune ierr = SNESLineSearchGetNorms(snes->linesearch, &xnorm, &fnorm, &ynorm);CHKERRQ(ierr); 4530c777b0cSPeter Brune if (qn->scale_type == SNES_QN_SCALE_LINESEARCH) { 45405ee83feSPeter Brune ierr = SNESLineSearchGetLambda(snes->linesearch, &qn->scaling);CHKERRQ(ierr); 4550ecc9e1dSPeter Brune } 4563af51624SPeter Brune 45788d374b2SPeter Brune /* convergence monitoring */ 458b21d5a53SPeter 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); 459b21d5a53SPeter Brune 460b28a06ddSPeter Brune if (snes->pc && snes->pcside == PC_RIGHT) { 461b28a06ddSPeter Brune ierr = PetscLogEventBegin(SNES_NPCSolve,snes->pc,X,0,0);CHKERRQ(ierr); 462b28a06ddSPeter Brune ierr = SNESSolve(snes->pc,snes->vec_rhs,X);CHKERRQ(ierr); 463b28a06ddSPeter Brune ierr = PetscLogEventEnd(SNES_NPCSolve,snes->pc,X,0,0);CHKERRQ(ierr); 464ddd40ce5SPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 465ddd40ce5SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 466ddd40ce5SPeter Brune snes->reason = SNES_DIVERGED_INNER; 467ddd40ce5SPeter Brune PetscFunctionReturn(0); 468ddd40ce5SPeter Brune } 469ddd40ce5SPeter Brune ierr = SNESGetPCFunction(snes,F,&fnorm);CHKERRQ(ierr); 470b28a06ddSPeter Brune } 471b28a06ddSPeter Brune 472360c497dSPeter Brune ierr = SNESSetIterationNumber(snes, i+1);CHKERRQ(ierr); 473360c497dSPeter Brune ierr = SNESSetFunctionNorm(snes, fnorm);CHKERRQ(ierr); 474360c497dSPeter Brune 475a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,snes->norm,snes->iter);CHKERRQ(ierr); 4768409ca45SMatthew G Knepley ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 4774b11644fSPeter Brune /* set parameter for default relative tolerance convergence test */ 478d484d688SPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 4794b11644fSPeter Brune if (snes->reason) PetscFunctionReturn(0); 480b28a06ddSPeter Brune if (snes->pc && snes->pcside == PC_LEFT && snes->functype == SNES_FUNCTION_UNPRECONDITIONED) { 48147f26062SPeter Brune ierr = SNESApplyPC(snes,X,F,&fnorm,D);CHKERRQ(ierr); 482b7281c8aSPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 483b7281c8aSPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 484b7281c8aSPeter Brune snes->reason = SNES_DIVERGED_INNER; 485b7281c8aSPeter Brune PetscFunctionReturn(0); 486b7281c8aSPeter Brune } 48788d374b2SPeter Brune } else { 48888d374b2SPeter Brune ierr = VecCopy(F, D);CHKERRQ(ierr); 48988d374b2SPeter Brune } 4900c777b0cSPeter Brune powell = PETSC_FALSE; 4910c777b0cSPeter Brune if (qn->restart_type == SNES_QN_RESTART_POWELL) { 4926bf1b2e5SPeter Brune /* check restart by Powell's Criterion: |F^T H_0 Fold| > 0.2 * |Fold^T H_0 Fold| */ 49323c918e7SPeter Brune if (qn->scale_type == SNES_QN_SCALE_JACOBIAN) { 49423c918e7SPeter Brune ierr = MatMult(snes->jacobian_pre,Dold,W);CHKERRQ(ierr); 49523c918e7SPeter Brune } else { 49623c918e7SPeter Brune ierr = VecCopy(Dold,W);CHKERRQ(ierr); 49723c918e7SPeter Brune } 49823c918e7SPeter Brune ierr = VecDotBegin(W, Dold, &DolddotDold);CHKERRQ(ierr); 49923c918e7SPeter Brune ierr = VecDotBegin(W, D, &DolddotD);CHKERRQ(ierr); 50023c918e7SPeter Brune ierr = VecDotEnd(W, Dold, &DolddotDold);CHKERRQ(ierr); 50123c918e7SPeter Brune ierr = VecDotEnd(W, D, &DolddotD);CHKERRQ(ierr); 5020c777b0cSPeter Brune if (PetscAbs(PetscRealPart(DolddotD)) > qn->powell_gamma*PetscAbs(PetscRealPart(DolddotDold))) powell = PETSC_TRUE; 5030c777b0cSPeter Brune } 5040c777b0cSPeter Brune periodic = PETSC_FALSE; 505b8840d6bSPeter Brune if (qn->restart_type == SNES_QN_RESTART_PERIODIC) { 506b8840d6bSPeter Brune if (i_r>qn->m-1) periodic = PETSC_TRUE; 5070c777b0cSPeter Brune } 5080c777b0cSPeter Brune /* restart if either powell or periodic restart is satisfied. */ 5090c777b0cSPeter Brune if (powell || periodic) { 5105ba6227bSPeter Brune if (qn->monitor) { 5115ba6227bSPeter Brune ierr = PetscViewerASCIIAddTab(qn->monitor,((PetscObject)snes)->tablevel+2);CHKERRQ(ierr); 512516fe3c3SPeter Brune ierr = PetscViewerASCIIPrintf(qn->monitor, "restart! |%14.12e| > %4.2f*|%14.12e| or i_r = %d\n", PetscRealPart(DolddotD), qn->powell_gamma, PetscRealPart(DolddotDold), i_r);CHKERRQ(ierr); 5135ba6227bSPeter Brune ierr = PetscViewerASCIISubtractTab(qn->monitor,((PetscObject)snes)->tablevel+2);CHKERRQ(ierr); 5145ba6227bSPeter Brune } 5155ba6227bSPeter Brune i_r = -1; 5165ba6227bSPeter Brune /* general purpose update */ 5175ba6227bSPeter Brune if (snes->ops->update) { 5185ba6227bSPeter Brune ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 5195ba6227bSPeter Brune } 5200c777b0cSPeter Brune if (qn->scale_type == SNES_QN_SCALE_JACOBIAN) { 5210ecc9e1dSPeter Brune ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 5228cba9625SJed Brown ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr); 5230ecc9e1dSPeter Brune } 5240ecc9e1dSPeter Brune } 52570d3b23bSPeter Brune /* general purpose update */ 52670d3b23bSPeter Brune if (snes->ops->update) { 52770d3b23bSPeter Brune ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 52870d3b23bSPeter Brune } 5295ba6227bSPeter Brune } 5304b11644fSPeter Brune if (i == snes->max_its) { 5314b11644fSPeter Brune ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", snes->max_its);CHKERRQ(ierr); 5324b11644fSPeter Brune if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 5334b11644fSPeter Brune } 5344b11644fSPeter Brune PetscFunctionReturn(0); 5354b11644fSPeter Brune } 5364b11644fSPeter Brune 5374b11644fSPeter Brune #undef __FUNCT__ 5384b11644fSPeter Brune #define __FUNCT__ "SNESSetUp_QN" 5394b11644fSPeter Brune static PetscErrorCode SNESSetUp_QN(SNES snes) 5404b11644fSPeter Brune { 5419f83bee8SJed Brown SNES_QN *qn = (SNES_QN*)snes->data; 5424b11644fSPeter Brune PetscErrorCode ierr; 543335fb975SPeter Brune 5444b11644fSPeter Brune PetscFunctionBegin; 545b8840d6bSPeter Brune ierr = VecDuplicateVecs(snes->vec_sol, qn->m, &qn->U);CHKERRQ(ierr); 54659e7931aSPeter Brune if (qn->type != SNES_QN_BROYDEN) ierr = VecDuplicateVecs(snes->vec_sol, qn->m, &qn->V);CHKERRQ(ierr); 5475c7a0a03SPeter Brune ierr = PetscMalloc4(qn->m, PetscScalar, &qn->alpha, 5488e231d97SPeter Brune qn->m, PetscScalar, &qn->beta, 5495c7a0a03SPeter Brune qn->m, PetscScalar, &qn->dXtdF, 5505c7a0a03SPeter Brune qn->m, PetscReal, &qn->lambda);CHKERRQ(ierr); 5518e231d97SPeter Brune 55218aa0c0cSPeter Brune if (qn->singlereduction) { 5538e231d97SPeter Brune ierr = PetscMalloc3(qn->m*qn->m, PetscScalar, &qn->dXdFmat, 5548e231d97SPeter Brune qn->m, PetscScalar, &qn->dFtdX, 5558e231d97SPeter Brune qn->m, PetscScalar, &qn->YtdX);CHKERRQ(ierr); 5568e231d97SPeter Brune } 557fa0ddf94SBarry Smith ierr = SNESSetWorkVecs(snes,4);CHKERRQ(ierr); 558*60c08b40SPeter Brune /* set method defaults */ 559*60c08b40SPeter Brune if (qn->scale_type == -1) { 560*60c08b40SPeter Brune if (qn->type == SNES_QN_BADBROYDEN) { 561*60c08b40SPeter Brune qn->scale_type = SNES_QN_SCALE_NONE; 562*60c08b40SPeter Brune } else { 563*60c08b40SPeter Brune qn->scale_type = SNES_QN_SCALE_SHANNO; 564*60c08b40SPeter Brune } 565*60c08b40SPeter Brune } 566*60c08b40SPeter Brune if (qn->restart_type == -1) { 567*60c08b40SPeter Brune if (qn->type == SNES_QN_LBFGS) { 568*60c08b40SPeter Brune qn->restart_type = SNES_QN_RESTART_POWELL; 569*60c08b40SPeter Brune } else { 570*60c08b40SPeter Brune qn->restart_type = SNES_QN_RESTART_PERIODIC; 571*60c08b40SPeter Brune } 572*60c08b40SPeter Brune } 573*60c08b40SPeter Brune 5740c777b0cSPeter Brune if (qn->scale_type == SNES_QN_SCALE_JACOBIAN) { 5758e231d97SPeter Brune ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr); 5768e231d97SPeter Brune } 5776c67d002SPeter Brune if (snes->pcside == PC_LEFT && snes->functype == SNES_FUNCTION_DEFAULT) {snes->functype = SNES_FUNCTION_UNPRECONDITIONED;} 5784b11644fSPeter Brune PetscFunctionReturn(0); 5794b11644fSPeter Brune } 5804b11644fSPeter Brune 5814b11644fSPeter Brune #undef __FUNCT__ 5824b11644fSPeter Brune #define __FUNCT__ "SNESReset_QN" 5834b11644fSPeter Brune static PetscErrorCode SNESReset_QN(SNES snes) 5844b11644fSPeter Brune { 5854b11644fSPeter Brune PetscErrorCode ierr; 5869f83bee8SJed Brown SNES_QN *qn; 5870adebc6cSBarry Smith 5884b11644fSPeter Brune PetscFunctionBegin; 5894b11644fSPeter Brune if (snes->data) { 5909f83bee8SJed Brown qn = (SNES_QN*)snes->data; 591b8840d6bSPeter Brune if (qn->U) { 592b8840d6bSPeter Brune ierr = VecDestroyVecs(qn->m, &qn->U);CHKERRQ(ierr); 5934b11644fSPeter Brune } 594b8840d6bSPeter Brune if (qn->V) { 595b8840d6bSPeter Brune ierr = VecDestroyVecs(qn->m, &qn->V);CHKERRQ(ierr); 5964b11644fSPeter Brune } 59718aa0c0cSPeter Brune if (qn->singlereduction) { 5988e231d97SPeter Brune ierr = PetscFree3(qn->dXdFmat, qn->dFtdX, qn->YtdX);CHKERRQ(ierr); 5998e231d97SPeter Brune } 6005c7a0a03SPeter Brune ierr = PetscFree4(qn->alpha,qn->beta,qn->dXtdF,qn->lambda);CHKERRQ(ierr); 6014b11644fSPeter Brune } 6024b11644fSPeter Brune PetscFunctionReturn(0); 6034b11644fSPeter Brune } 6044b11644fSPeter Brune 6054b11644fSPeter Brune #undef __FUNCT__ 6064b11644fSPeter Brune #define __FUNCT__ "SNESDestroy_QN" 6074b11644fSPeter Brune static PetscErrorCode SNESDestroy_QN(SNES snes) 6084b11644fSPeter Brune { 6094b11644fSPeter Brune PetscErrorCode ierr; 6106e111a19SKarl Rupp 6114b11644fSPeter Brune PetscFunctionBegin; 6124b11644fSPeter Brune ierr = SNESReset_QN(snes);CHKERRQ(ierr); 6134b11644fSPeter Brune ierr = PetscFree(snes->data);CHKERRQ(ierr); 614bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"",NULL);CHKERRQ(ierr); 6154b11644fSPeter Brune PetscFunctionReturn(0); 6164b11644fSPeter Brune } 6174b11644fSPeter Brune 6184b11644fSPeter Brune #undef __FUNCT__ 6194b11644fSPeter Brune #define __FUNCT__ "SNESSetFromOptions_QN" 6204b11644fSPeter Brune static PetscErrorCode SNESSetFromOptions_QN(SNES snes) 6214b11644fSPeter Brune { 6224b11644fSPeter Brune 6234b11644fSPeter Brune PetscErrorCode ierr; 6242150357eSBarry Smith SNES_QN *qn = (SNES_QN*)snes->data; 62588f769c5SPeter Brune PetscBool monflg = PETSC_FALSE,flg; 626f1c6b773SPeter Brune SNESLineSearch linesearch; 6272150357eSBarry Smith SNESQNRestartType rtype = qn->restart_type; 6282150357eSBarry Smith SNESQNScaleType stype = qn->scale_type; 6292150357eSBarry Smith 6304b11644fSPeter Brune PetscFunctionBegin; 6314b11644fSPeter Brune ierr = PetscOptionsHead("SNES QN options");CHKERRQ(ierr); 6320298fd71SBarry Smith ierr = PetscOptionsInt("-snes_qn_m","Number of past states saved for L-BFGS methods","SNESQN",qn->m,&qn->m,NULL);CHKERRQ(ierr); 6330298fd71SBarry Smith ierr = PetscOptionsReal("-snes_qn_powell_gamma","Powell angle tolerance", "SNESQN", qn->powell_gamma, &qn->powell_gamma, NULL);CHKERRQ(ierr); 6340298fd71SBarry Smith ierr = PetscOptionsReal("-snes_qn_powell_downhill","Powell descent tolerance", "SNESQN", qn->powell_downhill, &qn->powell_downhill, NULL);CHKERRQ(ierr); 6350298fd71SBarry Smith ierr = PetscOptionsBool("-snes_qn_monitor", "Monitor for the QN methods", "SNESQN", monflg, &monflg, NULL);CHKERRQ(ierr); 6360298fd71SBarry Smith ierr = PetscOptionsBool("-snes_qn_single_reduction", "Aggregate reductions", "SNESQN", qn->singlereduction, &qn->singlereduction, NULL);CHKERRQ(ierr); 63788f769c5SPeter Brune ierr = PetscOptionsEnum("-snes_qn_scale_type","Scaling type","SNESQNSetScaleType",SNESQNScaleTypes,(PetscEnum)stype,(PetscEnum*)&stype,&flg);CHKERRQ(ierr); 63888f769c5SPeter Brune if (flg) ierr = SNESQNSetScaleType(snes,stype);CHKERRQ(ierr); 63988f769c5SPeter Brune 64088f769c5SPeter Brune ierr = PetscOptionsEnum("-snes_qn_restart_type","Restart type","SNESQNSetRestartType",SNESQNRestartTypes,(PetscEnum)rtype,(PetscEnum*)&rtype,&flg);CHKERRQ(ierr); 64188f769c5SPeter Brune if (flg) ierr = SNESQNSetRestartType(snes,rtype);CHKERRQ(ierr); 64288f769c5SPeter Brune 643b8840d6bSPeter Brune ierr = PetscOptionsEnum("-snes_qn_type","Quasi-Newton update type","",SNESQNTypes, 6440298fd71SBarry Smith (PetscEnum)qn->type,(PetscEnum*)&qn->type,NULL);CHKERRQ(ierr); 6454b11644fSPeter Brune ierr = PetscOptionsTail();CHKERRQ(ierr); 6469e764e56SPeter Brune if (!snes->linesearch) { 6477601faf0SJed Brown ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr); 648*60c08b40SPeter Brune if (qn->type == SNES_QN_LBFGS) { 6491a4f838cSPeter Brune ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHCP);CHKERRQ(ierr); 650*60c08b40SPeter Brune } else if (qn->type == SNES_QN_BROYDEN) { 651*60c08b40SPeter Brune ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHBASIC);CHKERRQ(ierr); 652*60c08b40SPeter Brune } else { 653*60c08b40SPeter Brune ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHL2);CHKERRQ(ierr); 654*60c08b40SPeter Brune } 6559e764e56SPeter Brune } 65644f7e39eSPeter Brune if (monflg) { 657ce94432eSBarry Smith qn->monitor = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); 65844f7e39eSPeter Brune } 6594b11644fSPeter Brune PetscFunctionReturn(0); 6604b11644fSPeter Brune } 6614b11644fSPeter Brune 66292c02d66SPeter Brune 6630c777b0cSPeter Brune #undef __FUNCT__ 6640c777b0cSPeter Brune #define __FUNCT__ "SNESQNSetRestartType" 6650c777b0cSPeter Brune /*@ 6660c777b0cSPeter Brune SNESQNSetRestartType - Sets the restart type for SNESQN. 6670c777b0cSPeter Brune 6680c777b0cSPeter Brune Logically Collective on SNES 6690c777b0cSPeter Brune 6700c777b0cSPeter Brune Input Parameters: 6710c777b0cSPeter Brune + snes - the iterative context 6720c777b0cSPeter Brune - rtype - restart type 6730c777b0cSPeter Brune 6740c777b0cSPeter Brune Options Database: 6750c777b0cSPeter Brune + -snes_qn_restart_type<powell,periodic,none> - set the restart type 676b8840d6bSPeter Brune - -snes_qn_restart[10] - sets the number of iterations before restart for periodic 6770c777b0cSPeter Brune 6780c777b0cSPeter Brune Level: intermediate 6790c777b0cSPeter Brune 6800c777b0cSPeter Brune SNESQNRestartTypes: 6810c777b0cSPeter Brune + SNES_QN_RESTART_NONE - never restart 6820c777b0cSPeter Brune . SNES_QN_RESTART_POWELL - restart based upon descent criteria 6830c777b0cSPeter Brune - SNES_QN_RESTART_PERIODIC - restart after a fixed number of iterations 6840c777b0cSPeter Brune 6850c777b0cSPeter Brune Notes: 6860c777b0cSPeter Brune The default line search used is the L2 line search and it requires two additional function evaluations. 6870c777b0cSPeter Brune 6880c777b0cSPeter Brune .keywords: SNES, SNESQN, restart, type, set SNESLineSearch 6890c777b0cSPeter Brune @*/ 6902150357eSBarry Smith PetscErrorCode SNESQNSetRestartType(SNES snes, SNESQNRestartType rtype) 6912150357eSBarry Smith { 6920c777b0cSPeter Brune PetscErrorCode ierr; 6936e111a19SKarl Rupp 6940c777b0cSPeter Brune PetscFunctionBegin; 6950c777b0cSPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 6960c777b0cSPeter Brune ierr = PetscTryMethod(snes,"SNESQNSetRestartType_C",(SNES,SNESQNRestartType),(snes,rtype));CHKERRQ(ierr); 6970c777b0cSPeter Brune PetscFunctionReturn(0); 6980c777b0cSPeter Brune } 6990c777b0cSPeter Brune 7000c777b0cSPeter Brune #undef __FUNCT__ 7010c777b0cSPeter Brune #define __FUNCT__ "SNESQNSetScaleType" 7020c777b0cSPeter Brune /*@ 7030c777b0cSPeter Brune SNESQNSetScaleType - Sets the scaling type for the inner inverse jacobian in SNESQN. 7040c777b0cSPeter Brune 7050c777b0cSPeter Brune Logically Collective on SNES 7060c777b0cSPeter Brune 7070c777b0cSPeter Brune Input Parameters: 7080c777b0cSPeter Brune + snes - the iterative context 7090c777b0cSPeter Brune - stype - scale type 7100c777b0cSPeter Brune 7110c777b0cSPeter Brune Options Database: 7120c777b0cSPeter Brune . -snes_qn_scale_type<shanno,none,linesearch,jacobian> 7130c777b0cSPeter Brune 7140c777b0cSPeter Brune Level: intermediate 7150c777b0cSPeter Brune 7160c777b0cSPeter Brune SNESQNSelectTypes: 7170c777b0cSPeter Brune + SNES_QN_SCALE_NONE - don't scale the problem 7180c777b0cSPeter Brune . SNES_QN_SCALE_SHANNO - use shanno scaling 7190c777b0cSPeter Brune . SNES_QN_SCALE_LINESEARCH - scale based upon line search lambda 7200c777b0cSPeter Brune - SNES_QN_SCALE_JACOBIAN - scale by inverting a previously computed Jacobian. 7210c777b0cSPeter Brune 7220c777b0cSPeter Brune .keywords: SNES, SNESQN, scaling, type, set SNESLineSearch 7230c777b0cSPeter Brune @*/ 7240c777b0cSPeter Brune 7252150357eSBarry Smith PetscErrorCode SNESQNSetScaleType(SNES snes, SNESQNScaleType stype) 7262150357eSBarry Smith { 7270c777b0cSPeter Brune PetscErrorCode ierr; 7286e111a19SKarl Rupp 7290c777b0cSPeter Brune PetscFunctionBegin; 7300c777b0cSPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 7310c777b0cSPeter Brune ierr = PetscTryMethod(snes,"SNESQNSetScaleType_C",(SNES,SNESQNScaleType),(snes,stype));CHKERRQ(ierr); 7320c777b0cSPeter Brune PetscFunctionReturn(0); 7330c777b0cSPeter Brune } 7340c777b0cSPeter Brune 7350c777b0cSPeter Brune #undef __FUNCT__ 7360c777b0cSPeter Brune #define __FUNCT__ "SNESQNSetScaleType_QN" 7370adebc6cSBarry Smith PetscErrorCode SNESQNSetScaleType_QN(SNES snes, SNESQNScaleType stype) 7380adebc6cSBarry Smith { 7390c777b0cSPeter Brune SNES_QN *qn = (SNES_QN*)snes->data; 7406e111a19SKarl Rupp 7410c777b0cSPeter Brune PetscFunctionBegin; 7420c777b0cSPeter Brune qn->scale_type = stype; 7430c777b0cSPeter Brune PetscFunctionReturn(0); 7440c777b0cSPeter Brune } 7450c777b0cSPeter Brune 7460c777b0cSPeter Brune #undef __FUNCT__ 7470c777b0cSPeter Brune #define __FUNCT__ "SNESQNSetRestartType_QN" 7480adebc6cSBarry Smith PetscErrorCode SNESQNSetRestartType_QN(SNES snes, SNESQNRestartType rtype) 7490adebc6cSBarry Smith { 7500c777b0cSPeter Brune SNES_QN *qn = (SNES_QN*)snes->data; 7516e111a19SKarl Rupp 7520c777b0cSPeter Brune PetscFunctionBegin; 7530c777b0cSPeter Brune qn->restart_type = rtype; 7540c777b0cSPeter Brune PetscFunctionReturn(0); 7550c777b0cSPeter Brune } 7560c777b0cSPeter Brune 7574b11644fSPeter Brune /* -------------------------------------------------------------------------- */ 7584b11644fSPeter Brune /*MC 7594b11644fSPeter Brune SNESQN - Limited-Memory Quasi-Newton methods for the solution of nonlinear systems. 7604b11644fSPeter Brune 7616cc8130cSPeter Brune Options Database: 7626cc8130cSPeter Brune 7636cc8130cSPeter Brune + -snes_qn_m - Number of past states saved for the L-Broyden methods. 7641867fe5bSPeter Brune . -snes_qn_powell_angle - Angle condition for restart. 7651867fe5bSPeter Brune . -snes_qn_powell_descent - Descent condition for restart. 76672835e02SPeter Brune . -snes_linesearch_type <cp, l2, basic> - Type of line search. 76744f7e39eSPeter Brune - -snes_qn_monitor - Monitors the quasi-newton jacobian. 7686cc8130cSPeter Brune 769b8840d6bSPeter Brune Notes: This implements the L-BFGS, Broyden, and "Bad" Broyden algorithms for the solution of F(x) = b using 770b8840d6bSPeter Brune previous change in F(x) and x to form the approximate inverse Jacobian using a series of multiplicative rank-one 771b8840d6bSPeter Brune updates. 7726cc8130cSPeter Brune 7731867fe5bSPeter Brune When using a nonlinear preconditioner, one has two options as to how the preconditioner is applied. The first of 7741867fe5bSPeter Brune these options, sequential, uses the preconditioner to generate a new solution and function and uses those at this 7751867fe5bSPeter Brune iteration as the current iteration's values when constructing the approximate jacobian. The second, composed, 7761867fe5bSPeter Brune perturbs the problem the jacobian represents to be P(x, b) - x = 0, where P(x, b) is the preconditioner. 7771867fe5bSPeter Brune 7786cc8130cSPeter Brune References: 7796cc8130cSPeter Brune 7800a8e8854SPeter Brune Kelley, C.T., Iterative Methods for Linear and Nonlinear Equations, Chapter 8, SIAM, 1995. 7816cc8130cSPeter Brune 7820a8e8854SPeter Brune R. Byrd, J. Nocedal, R. Schnabel, Representations of Quasi-Newton Matrices and their use in Limited Memory Methods, 7830a8e8854SPeter Brune Technical Report, Northwestern University, June 1992. 7840a8e8854SPeter Brune 7850a8e8854SPeter Brune Peter N. Brown, Alan C. Hindmarsh, Homer F. Walker, Experiments with Quasi-Newton Methods in Solving Stiff ODE 7860a8e8854SPeter Brune Systems, SIAM J. Sci. Stat. Comput. Vol 6(2), April 1985. 787b8840d6bSPeter Brune 7884b11644fSPeter Brune 7894b11644fSPeter Brune Level: beginner 7904b11644fSPeter Brune 79104d7464bSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESNEWTONLS, SNESNEWTONTR 7926cc8130cSPeter Brune 7934b11644fSPeter Brune M*/ 7944b11644fSPeter Brune #undef __FUNCT__ 7954b11644fSPeter Brune #define __FUNCT__ "SNESCreate_QN" 7968cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESCreate_QN(SNES snes) 7974b11644fSPeter Brune { 7984b11644fSPeter Brune PetscErrorCode ierr; 7999f83bee8SJed Brown SNES_QN *qn; 8004b11644fSPeter Brune 8014b11644fSPeter Brune PetscFunctionBegin; 8024b11644fSPeter Brune snes->ops->setup = SNESSetUp_QN; 8034b11644fSPeter Brune snes->ops->solve = SNESSolve_QN; 8044b11644fSPeter Brune snes->ops->destroy = SNESDestroy_QN; 8054b11644fSPeter Brune snes->ops->setfromoptions = SNESSetFromOptions_QN; 8064b11644fSPeter Brune snes->ops->view = 0; 8074b11644fSPeter Brune snes->ops->reset = SNESReset_QN; 8084b11644fSPeter Brune 80947f26062SPeter Brune snes->pcside = PC_LEFT; 81047f26062SPeter Brune 81142f4f86dSBarry Smith snes->usespc = PETSC_TRUE; 81242f4f86dSBarry Smith snes->usesksp = PETSC_FALSE; 81342f4f86dSBarry Smith 81488976e71SPeter Brune if (!snes->tolerancesset) { 8150e444f03SPeter Brune snes->max_funcs = 30000; 8160e444f03SPeter Brune snes->max_its = 10000; 81788976e71SPeter Brune } 8180e444f03SPeter Brune 8199f83bee8SJed Brown ierr = PetscNewLog(snes,SNES_QN,&qn);CHKERRQ(ierr); 8204b11644fSPeter Brune snes->data = (void*) qn; 8210ecc9e1dSPeter Brune qn->m = 10; 822b21d5a53SPeter Brune qn->scaling = 1.0; 8230298fd71SBarry Smith qn->U = NULL; 8240298fd71SBarry Smith qn->V = NULL; 8250298fd71SBarry Smith qn->dXtdF = NULL; 8260298fd71SBarry Smith qn->dFtdX = NULL; 8270298fd71SBarry Smith qn->dXdFmat = NULL; 8280298fd71SBarry Smith qn->monitor = NULL; 8291c6523dcSPeter Brune qn->singlereduction = PETSC_TRUE; 830b8840d6bSPeter Brune qn->powell_gamma = 0.9999; 831*60c08b40SPeter Brune qn->scale_type = SNES_QN_SCALE_DEFAULT; 832*60c08b40SPeter Brune qn->restart_type = SNES_QN_RESTART_DEFAULT; 833b8840d6bSPeter Brune qn->type = SNES_QN_LBFGS; 834ea630c6eSPeter Brune 835bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESQNSetScaleType_C",SNESQNSetScaleType_QN);CHKERRQ(ierr); 836bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESQNSetRestartType_C",SNESQNSetRestartType_QN);CHKERRQ(ierr); 8374b11644fSPeter Brune PetscFunctionReturn(0); 8384b11644fSPeter Brune } 839