1fef7b6d8SPeter Brune #include <../src/snes/impls/ncg/snesncgimpl.h> 2fef7b6d8SPeter Brune 3fef7b6d8SPeter Brune #undef __FUNCT__ 4fef7b6d8SPeter Brune #define __FUNCT__ "SNESReset_NCG" 5fef7b6d8SPeter Brune PetscErrorCode SNESReset_NCG(SNES snes) 6fef7b6d8SPeter Brune { 7fef7b6d8SPeter Brune PetscErrorCode ierr; 8fef7b6d8SPeter Brune 9fef7b6d8SPeter Brune PetscFunctionBegin; 10fef7b6d8SPeter Brune if (snes->work) {ierr = VecDestroyVecs(snes->nwork,&snes->work);CHKERRQ(ierr);} 11fef7b6d8SPeter Brune PetscFunctionReturn(0); 12fef7b6d8SPeter Brune } 13fef7b6d8SPeter Brune 14fef7b6d8SPeter Brune /* 15fef7b6d8SPeter Brune SNESDestroy_NCG - Destroys the private SNES_NCG context that was created with SNESCreate_NCG(). 16fef7b6d8SPeter Brune 17fef7b6d8SPeter Brune Input Parameter: 18fef7b6d8SPeter Brune . snes - the SNES context 19fef7b6d8SPeter Brune 20fef7b6d8SPeter Brune Application Interface Routine: SNESDestroy() 21fef7b6d8SPeter Brune */ 22fef7b6d8SPeter Brune #undef __FUNCT__ 23fef7b6d8SPeter Brune #define __FUNCT__ "SNESDestroy_NCG" 24fef7b6d8SPeter Brune PetscErrorCode SNESDestroy_NCG(SNES snes) 25fef7b6d8SPeter Brune { 26fef7b6d8SPeter Brune PetscErrorCode ierr; 27fef7b6d8SPeter Brune 28fef7b6d8SPeter Brune PetscFunctionBegin; 29fef7b6d8SPeter Brune ierr = SNESReset_NCG(snes);CHKERRQ(ierr); 30fef7b6d8SPeter Brune ierr = PetscFree(snes->data);CHKERRQ(ierr); 31fef7b6d8SPeter Brune PetscFunctionReturn(0); 32fef7b6d8SPeter Brune } 33fef7b6d8SPeter Brune 34fef7b6d8SPeter Brune /* 35fef7b6d8SPeter Brune SNESSetUp_NCG - Sets up the internal data structures for the later use 36fef7b6d8SPeter Brune of the SNESNCG nonlinear solver. 37fef7b6d8SPeter Brune 38fef7b6d8SPeter Brune Input Parameters: 39fef7b6d8SPeter Brune + snes - the SNES context 40fef7b6d8SPeter Brune - x - the solution vector 41fef7b6d8SPeter Brune 42fef7b6d8SPeter Brune Application Interface Routine: SNESSetUp() 43fef7b6d8SPeter Brune */ 44fef7b6d8SPeter Brune #undef __FUNCT__ 45fef7b6d8SPeter Brune #define __FUNCT__ "SNESSetUp_NCG" 46fef7b6d8SPeter Brune PetscErrorCode SNESSetUp_NCG(SNES snes) 47fef7b6d8SPeter Brune { 48fef7b6d8SPeter Brune PetscErrorCode ierr; 49fef7b6d8SPeter Brune 50fef7b6d8SPeter Brune PetscFunctionBegin; 51fef7b6d8SPeter Brune ierr = SNESDefaultGetWork(snes,2);CHKERRQ(ierr); 52fef7b6d8SPeter Brune PetscFunctionReturn(0); 53fef7b6d8SPeter Brune } 54fef7b6d8SPeter Brune /* 55fef7b6d8SPeter Brune SNESSetFromOptions_NCG - Sets various parameters for the SNESLS method. 56fef7b6d8SPeter Brune 57fef7b6d8SPeter Brune Input Parameter: 58fef7b6d8SPeter Brune . snes - the SNES context 59fef7b6d8SPeter Brune 60fef7b6d8SPeter Brune Application Interface Routine: SNESSetFromOptions() 61fef7b6d8SPeter Brune */ 62fef7b6d8SPeter Brune #undef __FUNCT__ 63fef7b6d8SPeter Brune #define __FUNCT__ "SNESSetFromOptions_NCG" 64fef7b6d8SPeter Brune static PetscErrorCode SNESSetFromOptions_NCG(SNES snes) 65fef7b6d8SPeter Brune { 66fef7b6d8SPeter Brune PetscErrorCode ierr; 67fef7b6d8SPeter Brune 68fef7b6d8SPeter Brune PetscFunctionBegin; 69fef7b6d8SPeter Brune ierr = PetscOptionsHead("SNES NCG options");CHKERRQ(ierr); 70fef7b6d8SPeter Brune ierr = PetscOptionsTail();CHKERRQ(ierr); 71fef7b6d8SPeter Brune PetscFunctionReturn(0); 72fef7b6d8SPeter Brune } 73fef7b6d8SPeter Brune 74fef7b6d8SPeter Brune /* 75fef7b6d8SPeter Brune SNESView_NCG - Prints info from the SNESNCG data structure. 76fef7b6d8SPeter Brune 77fef7b6d8SPeter Brune Input Parameters: 78fef7b6d8SPeter Brune + SNES - the SNES context 79fef7b6d8SPeter Brune - viewer - visualization context 80fef7b6d8SPeter Brune 81fef7b6d8SPeter Brune Application Interface Routine: SNESView() 82fef7b6d8SPeter Brune */ 83fef7b6d8SPeter Brune #undef __FUNCT__ 84fef7b6d8SPeter Brune #define __FUNCT__ "SNESView_NCG" 85fef7b6d8SPeter Brune static PetscErrorCode SNESView_NCG(SNES snes, PetscViewer viewer) 86fef7b6d8SPeter Brune { 87fef7b6d8SPeter Brune PetscBool iascii; 88fef7b6d8SPeter Brune PetscErrorCode ierr; 89fef7b6d8SPeter Brune 90fef7b6d8SPeter Brune PetscFunctionBegin; 91fef7b6d8SPeter Brune ierr = PetscTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 92fef7b6d8SPeter Brune if (iascii) { 93*ea630c6eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer," line search type variant: %s\n", SNESLineSearchTypeName(snes->ls_type));CHKERRQ(ierr); 94fef7b6d8SPeter Brune } 95fef7b6d8SPeter Brune PetscFunctionReturn(0); 96fef7b6d8SPeter Brune } 97fef7b6d8SPeter Brune 98fef7b6d8SPeter Brune #undef __FUNCT__ 99fef7b6d8SPeter Brune #define __FUNCT__ "SNESLineSearchNo_NCG" 100fef7b6d8SPeter Brune PetscErrorCode SNESLineSearchNo_NCG(SNES snes,void *lsctx,Vec X,Vec F,Vec Y,PetscReal fnorm,PetscReal dummyXnorm,Vec dummyG,Vec W,PetscReal *dummyYnorm,PetscReal *gnorm,PetscBool *flag) 101fef7b6d8SPeter Brune { 102fef7b6d8SPeter Brune PetscErrorCode ierr; 103fef7b6d8SPeter Brune 104fef7b6d8SPeter Brune PetscFunctionBegin; 105*ea630c6eSPeter Brune ierr = VecAXPY(X, snes->damping, Y);CHKERRQ(ierr); 106fef7b6d8SPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 107fef7b6d8SPeter Brune ierr = VecNorm(F, NORM_2, gnorm);CHKERRQ(ierr); 108fef7b6d8SPeter Brune if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Infinite or not-a-number generated norm"); 109fef7b6d8SPeter Brune PetscFunctionReturn(0); 110fef7b6d8SPeter Brune } 111fef7b6d8SPeter Brune 112fef7b6d8SPeter Brune #undef __FUNCT__ 113fef7b6d8SPeter Brune #define __FUNCT__ "SNESLineSearchNoNorms_NCG" 114fef7b6d8SPeter Brune PetscErrorCode SNESLineSearchNoNorms_NCG(SNES snes,void *lsctx,Vec X,Vec F,Vec Y,PetscReal fnorm,PetscReal dummyXnorm,Vec dummyG,Vec W,PetscReal *dummyYnorm,PetscReal *gnorm,PetscBool *flag) 115fef7b6d8SPeter Brune { 116fef7b6d8SPeter Brune PetscErrorCode ierr; 117fef7b6d8SPeter Brune 118fef7b6d8SPeter Brune PetscFunctionBegin; 119*ea630c6eSPeter Brune ierr = VecAXPY(X, snes->damping, Y);CHKERRQ(ierr); 120fef7b6d8SPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 121fef7b6d8SPeter Brune PetscFunctionReturn(0); 122fef7b6d8SPeter Brune } 123fef7b6d8SPeter Brune 124fef7b6d8SPeter Brune #undef __FUNCT__ 125fef7b6d8SPeter Brune #define __FUNCT__ "SNESLineSearchQuadratic_NCG" 126fef7b6d8SPeter Brune PetscErrorCode SNESLineSearchQuadratic_NCG(SNES snes,void *lsctx,Vec X,Vec F,Vec Y,PetscReal fnorm,PetscReal dummyXnorm,Vec G,Vec W,PetscReal *dummyYnorm,PetscReal *gnorm,PetscBool *flag) 127fef7b6d8SPeter Brune { 128fef7b6d8SPeter Brune PetscInt i; 129fef7b6d8SPeter Brune PetscReal alphas[3] = {0.0, 0.5, 1.0}; 130fef7b6d8SPeter Brune PetscReal norms[3]; 131fef7b6d8SPeter Brune PetscReal alpha,a,b; 132fef7b6d8SPeter Brune PetscErrorCode ierr; 133fef7b6d8SPeter Brune 134fef7b6d8SPeter Brune PetscFunctionBegin; 135fef7b6d8SPeter Brune norms[0] = fnorm; 136fef7b6d8SPeter Brune for(i=1; i < 3; ++i) { 137fef7b6d8SPeter Brune ierr = VecWAXPY(W, alphas[i], Y, X);CHKERRQ(ierr); /* W = X^n - \alpha Y */ 138fef7b6d8SPeter Brune ierr = SNESComputeFunction(snes, W, F);CHKERRQ(ierr); 139fef7b6d8SPeter Brune ierr = VecNorm(F, NORM_2, &norms[i]);CHKERRQ(ierr); 140fef7b6d8SPeter Brune } 141fef7b6d8SPeter Brune for(i = 0; i < 3; ++i) { 142fef7b6d8SPeter Brune norms[i] = PetscSqr(norms[i]); 143fef7b6d8SPeter Brune } 144fef7b6d8SPeter Brune /* Fit a quadratic: 145fef7b6d8SPeter Brune If we have x_{0,1,2} = 0, x_1, x_2 which generate norms y_{0,1,2} 146fef7b6d8SPeter Brune a = (x_1 y_2 - x_2 y_1 + (x_2 - x_1) y_0)/(x^2_2 x_1 - x_2 x^2_1) 147fef7b6d8SPeter Brune b = (x^2_1 y_2 - x^2_2 y_1 + (x^2_2 - x^2_1) y_0)/(x_2 x^2_1 - x^2_2 x_1) 148fef7b6d8SPeter Brune c = y_0 149fef7b6d8SPeter Brune x_min = -b/2a 150fef7b6d8SPeter Brune 151fef7b6d8SPeter Brune If we let x_{0,1,2} = 0, 0.5, 1.0 152fef7b6d8SPeter Brune a = 2 y_2 - 4 y_1 + 2 y_0 153fef7b6d8SPeter Brune b = -y_2 + 4 y_1 - 3 y_0 154fef7b6d8SPeter Brune c = y_0 155fef7b6d8SPeter Brune */ 156fef7b6d8SPeter Brune a = (alphas[1]*norms[2] - alphas[2]*norms[1] + (alphas[2] - alphas[1])*norms[0])/(PetscSqr(alphas[2])*alphas[1] - alphas[2]*PetscSqr(alphas[1])); 157fef7b6d8SPeter Brune b = (PetscSqr(alphas[1])*norms[2] - PetscSqr(alphas[2])*norms[1] + (PetscSqr(alphas[2]) - PetscSqr(alphas[1]))*norms[0])/(alphas[2]*PetscSqr(alphas[1]) - PetscSqr(alphas[2])*alphas[1]); 158fef7b6d8SPeter Brune /* Check for positive a (concave up) */ 159fef7b6d8SPeter Brune if (a >= 0.0) { 160fef7b6d8SPeter Brune alpha = -b/(2.0*a); 161fef7b6d8SPeter Brune alpha = PetscMin(alpha, alphas[2]); 162fef7b6d8SPeter Brune alpha = PetscMax(alpha, alphas[0]); 163fef7b6d8SPeter Brune } else { 164fef7b6d8SPeter Brune alpha = 1.0; 165fef7b6d8SPeter Brune } 166*ea630c6eSPeter Brune if (snes->ls_monitor) { 167*ea630c6eSPeter Brune ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 168*ea630c6eSPeter Brune ierr = PetscViewerASCIIPrintf(snes->ls_monitor," Line search: norms[0] = %g, norms[1] = %g, norms[2] = %g alpha %g\n", sqrt(norms[0]),sqrt(norms[1]),sqrt(norms[2]),alpha);CHKERRQ(ierr); 169*ea630c6eSPeter Brune ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 170fef7b6d8SPeter Brune } 171fef7b6d8SPeter Brune ierr = VecAXPY(X, alpha, Y);CHKERRQ(ierr); 172fef7b6d8SPeter Brune if (alpha != 1.0) { 173fef7b6d8SPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 174fef7b6d8SPeter Brune ierr = VecNorm(F, NORM_2, gnorm);CHKERRQ(ierr); 175fef7b6d8SPeter Brune } else { 176fef7b6d8SPeter Brune *gnorm = PetscSqrtReal(norms[2]); 177fef7b6d8SPeter Brune } 178fef7b6d8SPeter Brune if (alpha == 0.0) *flag = PETSC_FALSE; 179fef7b6d8SPeter Brune else *flag = PETSC_TRUE; 180fef7b6d8SPeter Brune PetscFunctionReturn(0); 181fef7b6d8SPeter Brune } 182fef7b6d8SPeter Brune 183*ea630c6eSPeter Brune 184*ea630c6eSPeter Brune 185*ea630c6eSPeter Brune #undef __FUNCT__ 186*ea630c6eSPeter Brune #define __FUNCT__ "SNESLineSearchExactLinear_NCG" 187*ea630c6eSPeter Brune PetscErrorCode SNESLineSearchExactLinear_NCG(SNES snes,void *lsctx,Vec X,Vec F,Vec Y,PetscReal fnorm,PetscReal dummyXnorm,Vec G,Vec W,PetscReal *dummyYnorm,PetscReal *gnorm,PetscBool *flag) 188*ea630c6eSPeter Brune { 189*ea630c6eSPeter Brune PetscScalar alpha, ptAp; 190*ea630c6eSPeter Brune PetscErrorCode ierr; 191*ea630c6eSPeter Brune /* SNES_NCG *ncg = (SNES_NCG *) snes->data; */ 192*ea630c6eSPeter Brune MatStructure flg = DIFFERENT_NONZERO_PATTERN; 193*ea630c6eSPeter Brune 194*ea630c6eSPeter Brune PetscFunctionBegin; 195*ea630c6eSPeter Brune /* 196*ea630c6eSPeter Brune 197*ea630c6eSPeter Brune The exact step size for linear CG is just: 198*ea630c6eSPeter Brune 199*ea630c6eSPeter Brune alpha = (r, r) / (p, Ap) = (f, f) / (y, Jy) 200*ea630c6eSPeter Brune 201*ea630c6eSPeter Brune */ 202*ea630c6eSPeter Brune 203*ea630c6eSPeter Brune ierr = SNESComputeJacobian(snes, X, &snes->jacobian, PETSC_NULL, &flg);CHKERRQ(ierr); 204*ea630c6eSPeter Brune ierr = VecDot(F, F, &alpha);CHKERRQ(ierr); 205*ea630c6eSPeter Brune ierr = MatMult(snes->jacobian, Y, W);CHKERRQ(ierr); 206*ea630c6eSPeter Brune ierr = VecDot(Y, W, &ptAp);CHKERRQ(ierr); 207*ea630c6eSPeter Brune alpha = alpha / ptAp; 208*ea630c6eSPeter Brune ierr = PetscPrintf(((PetscObject)snes)->comm, "alpha: %g\n", alpha);CHKERRQ(ierr); 209*ea630c6eSPeter Brune ierr = VecAXPY(X, alpha, Y);CHKERRQ(ierr); 210*ea630c6eSPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 211*ea630c6eSPeter Brune ierr = VecNorm(F, NORM_2, gnorm);CHKERRQ(ierr); 212*ea630c6eSPeter Brune PetscFunctionReturn(0); 213*ea630c6eSPeter Brune } 214*ea630c6eSPeter Brune 215fef7b6d8SPeter Brune /* 216fef7b6d8SPeter Brune SNESSolve_NCG - Solves a nonlinear system with the Nonlinear Conjugate Gradient method. 217fef7b6d8SPeter Brune 218fef7b6d8SPeter Brune Input Parameters: 219fef7b6d8SPeter Brune . snes - the SNES context 220fef7b6d8SPeter Brune 221fef7b6d8SPeter Brune Output Parameter: 222fef7b6d8SPeter Brune . outits - number of iterations until termination 223fef7b6d8SPeter Brune 224fef7b6d8SPeter Brune Application Interface Routine: SNESSolve() 225fef7b6d8SPeter Brune */ 226fef7b6d8SPeter Brune #undef __FUNCT__ 227fef7b6d8SPeter Brune #define __FUNCT__ "SNESSolve_NCG" 228fef7b6d8SPeter Brune PetscErrorCode SNESSolve_NCG(SNES snes) 229fef7b6d8SPeter Brune { 230302dbbaeSPeter Brune Vec X, dX, lX, F, W, B; 231fef7b6d8SPeter Brune PetscReal fnorm, dummyNorm; 232fef7b6d8SPeter Brune PetscScalar dXdot, dXdot_old; 233fef7b6d8SPeter Brune PetscInt maxits, i; 234fef7b6d8SPeter Brune PetscErrorCode ierr; 235fef7b6d8SPeter Brune SNESConvergedReason reason; 236fef7b6d8SPeter Brune PetscBool lsSuccess = PETSC_TRUE; 237fef7b6d8SPeter Brune PetscFunctionBegin; 238fef7b6d8SPeter Brune snes->reason = SNES_CONVERGED_ITERATING; 239fef7b6d8SPeter Brune 240fef7b6d8SPeter Brune maxits = snes->max_its; /* maximum number of iterations */ 241fef7b6d8SPeter Brune X = snes->vec_sol; /* X^n */ 242169e2be8SPeter Brune dX = snes->work[1]; /* the steepest direction */ 243169e2be8SPeter Brune lX = snes->vec_sol_update; /* the conjugate direction */ 244fef7b6d8SPeter Brune F = snes->vec_func; /* residual vector */ 245fef7b6d8SPeter Brune W = snes->work[0]; /* work vector for the line search */ 246302dbbaeSPeter Brune B = snes->vec_rhs; /* the right hand side */ 247fef7b6d8SPeter Brune 248fef7b6d8SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 249fef7b6d8SPeter Brune snes->iter = 0; 250fef7b6d8SPeter Brune snes->norm = 0.; 251fef7b6d8SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 252fef7b6d8SPeter Brune 253fef7b6d8SPeter Brune /* compute the initial function and preconditioned update delX */ 254fef7b6d8SPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 255fef7b6d8SPeter Brune if (snes->domainerror) { 256fef7b6d8SPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 257fef7b6d8SPeter Brune PetscFunctionReturn(0); 258fef7b6d8SPeter Brune } 259fef7b6d8SPeter Brune /* convergence test */ 260fef7b6d8SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 261fef7b6d8SPeter Brune if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Infinite or not-a-number generated in norm"); 262fef7b6d8SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 263fef7b6d8SPeter Brune snes->norm = fnorm; 264fef7b6d8SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 265fef7b6d8SPeter Brune SNESLogConvHistory(snes,fnorm,0); 266fef7b6d8SPeter Brune ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 267fef7b6d8SPeter Brune 268fef7b6d8SPeter Brune /* set parameter for default relative tolerance convergence test */ 269fef7b6d8SPeter Brune snes->ttol = fnorm*snes->rtol; 270fef7b6d8SPeter Brune /* test convergence */ 271fef7b6d8SPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 272fef7b6d8SPeter Brune if (snes->reason) PetscFunctionReturn(0); 273fef7b6d8SPeter Brune 274fef7b6d8SPeter Brune /* Call general purpose update function */ 275fef7b6d8SPeter Brune if (snes->ops->update) { 276fef7b6d8SPeter Brune ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 277fef7b6d8SPeter Brune } 278fef7b6d8SPeter Brune 279fef7b6d8SPeter Brune /* first update -- just use the (preconditioned) residual direction for the initial conjugate direction */ 280fef7b6d8SPeter Brune if (!snes->pc) { 281fef7b6d8SPeter Brune ierr = VecCopy(F, lX);CHKERRQ(ierr); 282fef7b6d8SPeter Brune ierr = VecScale(lX, -1.0);CHKERRQ(ierr); 283fef7b6d8SPeter Brune } else { 284fef7b6d8SPeter Brune ierr = VecCopy(X, lX);CHKERRQ(ierr); 28551e86f29SPeter Brune ierr = SNESSolve(snes->pc, snes->vec_rhs, lX);CHKERRQ(ierr); 286fef7b6d8SPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 287302dbbaeSPeter Brune ierr = VecAXPY(lX, -1.0, X);CHKERRQ(ierr); 28851e86f29SPeter Brune if (reason < 0 && (reason != SNES_DIVERGED_MAX_IT)) { 289fef7b6d8SPeter Brune snes->reason = SNES_DIVERGED_INNER; 290fef7b6d8SPeter Brune PetscFunctionReturn(0); 291fef7b6d8SPeter Brune } 292fef7b6d8SPeter Brune } 293fef7b6d8SPeter Brune ierr = VecDot(lX, lX, &dXdot);CHKERRQ(ierr); 294fef7b6d8SPeter Brune for(i = 1; i < maxits; i++) { 295fef7b6d8SPeter Brune lsSuccess = PETSC_TRUE; 296*ea630c6eSPeter Brune ierr = (*snes->ops->linesearch)(snes, snes->lsP, X, F, lX, fnorm, 0.0, 0, W, &dummyNorm, &fnorm, &lsSuccess);CHKERRQ(ierr); 297fef7b6d8SPeter Brune if (!lsSuccess) { 298fef7b6d8SPeter Brune if (++snes->numFailures >= snes->maxFailures) { 299fef7b6d8SPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 300fef7b6d8SPeter Brune break; 301fef7b6d8SPeter Brune } 302fef7b6d8SPeter Brune } 303fef7b6d8SPeter Brune if (snes->nfuncs >= snes->max_funcs) { 304fef7b6d8SPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 305fef7b6d8SPeter Brune break; 306fef7b6d8SPeter Brune } 307fef7b6d8SPeter Brune if (snes->domainerror) { 308fef7b6d8SPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 309fef7b6d8SPeter Brune PetscFunctionReturn(0); 310fef7b6d8SPeter Brune } 311302dbbaeSPeter Brune 312fef7b6d8SPeter Brune /* Monitor convergence */ 313fef7b6d8SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 314169e2be8SPeter Brune snes->iter = i; 315fef7b6d8SPeter Brune snes->norm = fnorm; 316fef7b6d8SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 317fef7b6d8SPeter Brune SNESLogConvHistory(snes,snes->norm,0); 318fef7b6d8SPeter Brune ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 319302dbbaeSPeter Brune 320fef7b6d8SPeter Brune /* Test for convergence */ 321fef7b6d8SPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 322fef7b6d8SPeter Brune if (snes->reason) break; 323302dbbaeSPeter Brune 324302dbbaeSPeter Brune /* Call general purpose update function */ 325302dbbaeSPeter Brune if (snes->ops->update) { 326302dbbaeSPeter Brune ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 327302dbbaeSPeter Brune } 328ee78dd50SPeter Brune if (!snes->pc) { 329302dbbaeSPeter Brune ierr = VecCopy(F,dX);CHKERRQ(ierr); 330302dbbaeSPeter Brune ierr = VecScale(dX,-1.0);CHKERRQ(ierr); 331302dbbaeSPeter Brune } else { 332302dbbaeSPeter Brune ierr = VecCopy(X,dX);CHKERRQ(ierr); 333ee78dd50SPeter Brune ierr = SNESSolve(snes->pc, snes->vec_rhs, dX);CHKERRQ(ierr); 334302dbbaeSPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 33551e86f29SPeter Brune if (reason < 0 && (reason != SNES_DIVERGED_MAX_IT)) { 336302dbbaeSPeter Brune snes->reason = SNES_DIVERGED_INNER; 337302dbbaeSPeter Brune PetscFunctionReturn(0); 338302dbbaeSPeter Brune } 339302dbbaeSPeter Brune ierr = VecAXPY(dX,-1.0,X);CHKERRQ(ierr); 340302dbbaeSPeter Brune } 341302dbbaeSPeter Brune 342169e2be8SPeter Brune /* compute the conjugate direction lX = dX + beta*lX with beta = ((dX, dX) / (dX_old, dX_old) (Fletcher-Reeves update)*/ 343302dbbaeSPeter Brune dXdot_old = dXdot; 344302dbbaeSPeter Brune ierr = VecDot(dX, dX, &dXdot);CHKERRQ(ierr); 345ee78dd50SPeter Brune #if 0 346421d9b32SPeter Brune if (1) 347169e2be8SPeter Brune ierr = PetscPrintf(PETSC_COMM_WORLD, "beta %e = %e / %e \n", dXdot / dXdot_old, dXdot, dXdot_old);CHKERRQ(ierr); 348ee78dd50SPeter Brune #endif 349302dbbaeSPeter Brune ierr = VecAYPX(lX, dXdot / dXdot_old, dX);CHKERRQ(ierr); 350302dbbaeSPeter Brune /* line search for the proper contribution of lX to the solution */ 351fef7b6d8SPeter Brune } 352fef7b6d8SPeter Brune if (i == maxits) { 353fef7b6d8SPeter Brune ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr); 354fef7b6d8SPeter Brune if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 355fef7b6d8SPeter Brune } 356fef7b6d8SPeter Brune PetscFunctionReturn(0); 357fef7b6d8SPeter Brune } 358fef7b6d8SPeter Brune 359fef7b6d8SPeter Brune /*MC 360fef7b6d8SPeter Brune SNESNCG - Nonlinear Conjugate-Gradient method for the solution of general nonlinear systems. 361fef7b6d8SPeter Brune 362fef7b6d8SPeter Brune Level: beginner 363fef7b6d8SPeter Brune 364fef7b6d8SPeter Brune Options Database: 365fef7b6d8SPeter Brune + -snes_ls_damping - damping factor to apply to F(x) (used only if -snes_ls is basic or basicnonorms) 366fef7b6d8SPeter Brune - -snes_ls <basic,basicnormnorms,quadratic> 367fef7b6d8SPeter Brune 368fef7b6d8SPeter Brune Notes: This solves the nonlinear system of equations F(x) = 0 using the nonlinear generalization of the conjugate 369fef7b6d8SPeter Brune gradient method. This may be used with a nonlinear preconditioner used to pick the new search directions, but otherwise 370fef7b6d8SPeter Brune chooses the initial search direction as F(x) for the initial guess x. 371fef7b6d8SPeter Brune 372fef7b6d8SPeter Brune 373fef7b6d8SPeter Brune .seealso: SNESCreate(), SNES, SNESSetType(), SNESLS, SNESTR, SNESNGMRES, SNESNQN 374fef7b6d8SPeter Brune M*/ 375fef7b6d8SPeter Brune EXTERN_C_BEGIN 376fef7b6d8SPeter Brune #undef __FUNCT__ 377fef7b6d8SPeter Brune #define __FUNCT__ "SNESCreate_NCG" 378fef7b6d8SPeter Brune PetscErrorCode SNESCreate_NCG(SNES snes) 379fef7b6d8SPeter Brune { 380fef7b6d8SPeter Brune PetscErrorCode ierr; 381*ea630c6eSPeter Brune SNES_NCG * neP; 382fef7b6d8SPeter Brune 383fef7b6d8SPeter Brune PetscFunctionBegin; 384fef7b6d8SPeter Brune snes->ops->destroy = SNESDestroy_NCG; 385fef7b6d8SPeter Brune snes->ops->setup = SNESSetUp_NCG; 386fef7b6d8SPeter Brune snes->ops->setfromoptions = SNESSetFromOptions_NCG; 387fef7b6d8SPeter Brune snes->ops->view = SNESView_NCG; 388fef7b6d8SPeter Brune snes->ops->solve = SNESSolve_NCG; 389fef7b6d8SPeter Brune snes->ops->reset = SNESReset_NCG; 390fef7b6d8SPeter Brune 391fef7b6d8SPeter Brune snes->usesksp = PETSC_FALSE; 392fef7b6d8SPeter Brune snes->usespc = PETSC_TRUE; 393fef7b6d8SPeter Brune 394fef7b6d8SPeter Brune ierr = PetscNewLog(snes, SNES_NCG, &neP);CHKERRQ(ierr); 395fef7b6d8SPeter Brune snes->data = (void*) neP; 396*ea630c6eSPeter Brune snes->ops->linesearch = SNESLineSearchQuadratic_NCG; 397*ea630c6eSPeter Brune snes->ops->linesearchquadratic = SNESLineSearchQuadratic_NCG; 398*ea630c6eSPeter Brune snes->ops->linesearchno = SNESLineSearchNo_NCG; 399*ea630c6eSPeter Brune snes->ops->linesearchnonorms = SNESLineSearchNoNorms_NCG; 400*ea630c6eSPeter Brune snes->ops->linesearchtest = SNESLineSearchExactLinear_NCG; 401*ea630c6eSPeter Brune snes->lsP = PETSC_NULL; 402*ea630c6eSPeter Brune snes->ops->postcheckstep = PETSC_NULL; 403*ea630c6eSPeter Brune snes->postcheck = PETSC_NULL; 404*ea630c6eSPeter Brune snes->ops->precheckstep = PETSC_NULL; 405*ea630c6eSPeter Brune snes->precheck = PETSC_NULL; 406fef7b6d8SPeter Brune PetscFunctionReturn(0); 407fef7b6d8SPeter Brune } 408fef7b6d8SPeter Brune EXTERN_C_END 409