1*028b6e76SBarry Smith 2*028b6e76SBarry Smith #include <../src/snes/impls/picard/picard.h> 3*028b6e76SBarry Smith 4*028b6e76SBarry Smith #undef __FUNCT__ 5*028b6e76SBarry Smith #define __FUNCT__ "SNESReset_Picard" 6*028b6e76SBarry Smith PetscErrorCode SNESReset_Picard(SNES snes) 7*028b6e76SBarry Smith { 8*028b6e76SBarry Smith PetscErrorCode ierr; 9*028b6e76SBarry Smith 10*028b6e76SBarry Smith PetscFunctionBegin; 11*028b6e76SBarry Smith if (snes->work) {ierr = VecDestroyVecs(snes->nwork,&snes->work);CHKERRQ(ierr);} 12*028b6e76SBarry Smith PetscFunctionReturn(0); 13*028b6e76SBarry Smith } 14*028b6e76SBarry Smith 15*028b6e76SBarry Smith /* 16*028b6e76SBarry Smith SNESDestroy_Picard - Destroys the private SNES_Picard context that was created with SNESCreate_Picard(). 17*028b6e76SBarry Smith 18*028b6e76SBarry Smith Input Parameter: 19*028b6e76SBarry Smith . snes - the SNES context 20*028b6e76SBarry Smith 21*028b6e76SBarry Smith Application Interface Routine: SNESDestroy() 22*028b6e76SBarry Smith */ 23*028b6e76SBarry Smith #undef __FUNCT__ 24*028b6e76SBarry Smith #define __FUNCT__ "SNESDestroy_Picard" 25*028b6e76SBarry Smith PetscErrorCode SNESDestroy_Picard(SNES snes) 26*028b6e76SBarry Smith { 27*028b6e76SBarry Smith PetscErrorCode ierr; 28*028b6e76SBarry Smith SNES_Picard *neP = (SNES_Picard*)snes->data; 29*028b6e76SBarry Smith 30*028b6e76SBarry Smith PetscFunctionBegin; 31*028b6e76SBarry Smith ierr = SNESReset_Picard(snes);CHKERRQ(ierr); 32*028b6e76SBarry Smith ierr = PetscViewerDestroy(&neP->monitor);CHKERRQ(ierr); 33*028b6e76SBarry Smith ierr = PetscFree(snes->data);CHKERRQ(ierr); 34*028b6e76SBarry Smith PetscFunctionReturn(0); 35*028b6e76SBarry Smith } 36*028b6e76SBarry Smith 37*028b6e76SBarry Smith /* 38*028b6e76SBarry Smith SNESSetUp_Picard - Sets up the internal data structures for the later use 39*028b6e76SBarry Smith of the SNESPICARD nonlinear solver. 40*028b6e76SBarry Smith 41*028b6e76SBarry Smith Input Parameters: 42*028b6e76SBarry Smith + snes - the SNES context 43*028b6e76SBarry Smith - x - the solution vector 44*028b6e76SBarry Smith 45*028b6e76SBarry Smith Application Interface Routine: SNESSetUp() 46*028b6e76SBarry Smith */ 47*028b6e76SBarry Smith #undef __FUNCT__ 48*028b6e76SBarry Smith #define __FUNCT__ "SNESSetUp_Picard" 49*028b6e76SBarry Smith PetscErrorCode SNESSetUp_Picard(SNES snes) 50*028b6e76SBarry Smith { 51*028b6e76SBarry Smith PetscErrorCode ierr; 52*028b6e76SBarry Smith 53*028b6e76SBarry Smith PetscFunctionBegin; 54*028b6e76SBarry Smith ierr = SNESDefaultGetWork(snes,1);CHKERRQ(ierr); 55*028b6e76SBarry Smith PetscFunctionReturn(0); 56*028b6e76SBarry Smith } 57*028b6e76SBarry Smith 58*028b6e76SBarry Smith EXTERN_C_BEGIN 59*028b6e76SBarry Smith #undef __FUNCT__ 60*028b6e76SBarry Smith #define __FUNCT__ "SNESLineSearchSetMonitor_Picard" 61*028b6e76SBarry Smith PetscErrorCode SNESLineSearchSetMonitor_Picard(SNES snes,PetscBool flg) 62*028b6e76SBarry Smith { 63*028b6e76SBarry Smith SNES_Picard *neP = (SNES_Picard*)snes->data; 64*028b6e76SBarry Smith PetscErrorCode ierr; 65*028b6e76SBarry Smith 66*028b6e76SBarry Smith PetscFunctionBegin; 67*028b6e76SBarry Smith if (flg && !neP->monitor) { 68*028b6e76SBarry Smith ierr = PetscViewerASCIIOpen(((PetscObject)snes)->comm,"stdout",&neP->monitor);CHKERRQ(ierr); 69*028b6e76SBarry Smith } else if (!flg && neP->monitor) { 70*028b6e76SBarry Smith ierr = PetscViewerDestroy(&neP->monitor);CHKERRQ(ierr); 71*028b6e76SBarry Smith } 72*028b6e76SBarry Smith PetscFunctionReturn(0); 73*028b6e76SBarry Smith } 74*028b6e76SBarry Smith EXTERN_C_END 75*028b6e76SBarry Smith 76*028b6e76SBarry Smith PetscErrorCode SNESLineSearchNoNorms_Picard(SNES,void*,Vec,Vec,Vec,PetscReal,PetscReal,Vec,Vec,PetscReal*,PetscReal*,PetscBool*); 77*028b6e76SBarry Smith PetscErrorCode SNESLineSearchNo_Picard(SNES,void*,Vec,Vec,Vec,PetscReal,PetscReal,Vec,Vec,PetscReal*,PetscReal*,PetscBool*); 78*028b6e76SBarry Smith PetscErrorCode SNESLineSearchQuadratic_Picard(SNES,void*,Vec,Vec,Vec,PetscReal,PetscReal,Vec,Vec,PetscReal*,PetscReal*,PetscBool*); 79*028b6e76SBarry Smith /* 80*028b6e76SBarry Smith SNESSetFromOptions_Picard - Sets various parameters for the SNESLS method. 81*028b6e76SBarry Smith 82*028b6e76SBarry Smith Input Parameter: 83*028b6e76SBarry Smith . snes - the SNES context 84*028b6e76SBarry Smith 85*028b6e76SBarry Smith Application Interface Routine: SNESSetFromOptions() 86*028b6e76SBarry Smith */ 87*028b6e76SBarry Smith #undef __FUNCT__ 88*028b6e76SBarry Smith #define __FUNCT__ "SNESSetFromOptions_Picard" 89*028b6e76SBarry Smith static PetscErrorCode SNESSetFromOptions_Picard(SNES snes) 90*028b6e76SBarry Smith { 91*028b6e76SBarry Smith SNES_Picard *ls = (SNES_Picard *)snes->data; 92*028b6e76SBarry Smith SNESLineSearchType indx; 93*028b6e76SBarry Smith PetscBool flg,set; 94*028b6e76SBarry Smith PetscErrorCode ierr; 95*028b6e76SBarry Smith 96*028b6e76SBarry Smith PetscFunctionBegin; 97*028b6e76SBarry Smith ierr = PetscOptionsHead("SNES Picard options");CHKERRQ(ierr); 98*028b6e76SBarry Smith ierr = PetscOptionsEnum("-snes_ls","Picard line search type","SNESLineSearchSet",SNESLineSearchTypes,(PetscEnum)ls->type,(PetscEnum*)&indx,&flg);CHKERRQ(ierr); 99*028b6e76SBarry Smith if (flg) { 100*028b6e76SBarry Smith ls->type = indx; 101*028b6e76SBarry Smith switch (indx) { 102*028b6e76SBarry Smith case SNES_LS_BASIC: 103*028b6e76SBarry Smith ierr = SNESLineSearchSet(snes,SNESLineSearchNo_Picard,PETSC_NULL);CHKERRQ(ierr); 104*028b6e76SBarry Smith break; 105*028b6e76SBarry Smith case SNES_LS_BASIC_NONORMS: 106*028b6e76SBarry Smith ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms_Picard,PETSC_NULL);CHKERRQ(ierr); 107*028b6e76SBarry Smith break; 108*028b6e76SBarry Smith case SNES_LS_QUADRATIC: 109*028b6e76SBarry Smith ierr = SNESLineSearchSet(snes,SNESLineSearchQuadratic_Picard,PETSC_NULL);CHKERRQ(ierr); 110*028b6e76SBarry Smith break; 111*028b6e76SBarry Smith case SNES_LS_CUBIC: 112*028b6e76SBarry Smith SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_SUP,"No support for cubic search"); 113*028b6e76SBarry Smith break; 114*028b6e76SBarry Smith } 115*028b6e76SBarry Smith } 116*028b6e76SBarry Smith ierr = PetscOptionsReal("-snes_ls_damping","Damping parameter","SNES",ls->damping,&ls->damping,&flg);CHKERRQ(ierr); 117*028b6e76SBarry Smith ierr = PetscOptionsBool("-snes_ls_monitor","Print progress of line searches","SNESLineSearchSetMonitor",ls->monitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr); 118*028b6e76SBarry Smith if (set) {ierr = SNESLineSearchSetMonitor(snes,flg);CHKERRQ(ierr);} 119*028b6e76SBarry Smith ierr = PetscOptionsTail();CHKERRQ(ierr); 120*028b6e76SBarry Smith PetscFunctionReturn(0); 121*028b6e76SBarry Smith } 122*028b6e76SBarry Smith 123*028b6e76SBarry Smith /* 124*028b6e76SBarry Smith SNESView_Picard - Prints info from the SNESPicard data structure. 125*028b6e76SBarry Smith 126*028b6e76SBarry Smith Input Parameters: 127*028b6e76SBarry Smith + SNES - the SNES context 128*028b6e76SBarry Smith - viewer - visualization context 129*028b6e76SBarry Smith 130*028b6e76SBarry Smith Application Interface Routine: SNESView() 131*028b6e76SBarry Smith */ 132*028b6e76SBarry Smith #undef __FUNCT__ 133*028b6e76SBarry Smith #define __FUNCT__ "SNESView_Picard" 134*028b6e76SBarry Smith static PetscErrorCode SNESView_Picard(SNES snes, PetscViewer viewer) 135*028b6e76SBarry Smith { 136*028b6e76SBarry Smith SNES_Picard *ls = (SNES_Picard *)snes->data; 137*028b6e76SBarry Smith PetscBool iascii; 138*028b6e76SBarry Smith PetscErrorCode ierr; 139*028b6e76SBarry Smith 140*028b6e76SBarry Smith PetscFunctionBegin; 141*028b6e76SBarry Smith ierr = PetscTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 142*028b6e76SBarry Smith if (iascii) { 143*028b6e76SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," picard variant: %s\n", SNESLineSearchTypeName(ls->type));CHKERRQ(ierr); 144*028b6e76SBarry Smith } 145*028b6e76SBarry Smith PetscFunctionReturn(0); 146*028b6e76SBarry Smith } 147*028b6e76SBarry Smith 148*028b6e76SBarry Smith #undef __FUNCT__ 149*028b6e76SBarry Smith #define __FUNCT__ "SNESLineSearchNo_Picard" 150*028b6e76SBarry Smith PetscErrorCode SNESLineSearchNo_Picard(SNES snes,void *lsctx,Vec X,Vec F,Vec Y,PetscReal fnorm,PetscReal dummyXnorm,Vec dummyG,Vec W,PetscReal *dummyYnorm,PetscReal *gnorm,PetscBool *flag) 151*028b6e76SBarry Smith { 152*028b6e76SBarry Smith PetscErrorCode ierr; 153*028b6e76SBarry Smith SNES_Picard *neP = (SNES_Picard *) snes->data; 154*028b6e76SBarry Smith 155*028b6e76SBarry Smith PetscFunctionBegin; 156*028b6e76SBarry Smith ierr = VecAXPY(X, neP->damping, Y);CHKERRQ(ierr); 157*028b6e76SBarry Smith ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 158*028b6e76SBarry Smith ierr = VecNorm(F, NORM_2, gnorm);CHKERRQ(ierr); 159*028b6e76SBarry Smith if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Infinite or not-a-number generated norm"); 160*028b6e76SBarry Smith PetscFunctionReturn(0); 161*028b6e76SBarry Smith } 162*028b6e76SBarry Smith 163*028b6e76SBarry Smith #undef __FUNCT__ 164*028b6e76SBarry Smith #define __FUNCT__ "SNESLineSearchNoNorms_Picard" 165*028b6e76SBarry Smith PetscErrorCode SNESLineSearchNoNorms_Picard(SNES snes,void *lsctx,Vec X,Vec F,Vec Y,PetscReal fnorm,PetscReal dummyXnorm,Vec dummyG,Vec W,PetscReal *dummyYnorm,PetscReal *gnorm,PetscBool *flag) 166*028b6e76SBarry Smith { 167*028b6e76SBarry Smith PetscErrorCode ierr; 168*028b6e76SBarry Smith SNES_Picard *neP = (SNES_Picard *) snes->data; 169*028b6e76SBarry Smith 170*028b6e76SBarry Smith PetscFunctionBegin; 171*028b6e76SBarry Smith ierr = VecAXPY(X, neP->damping, Y);CHKERRQ(ierr); 172*028b6e76SBarry Smith ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 173*028b6e76SBarry Smith PetscFunctionReturn(0); 174*028b6e76SBarry Smith } 175*028b6e76SBarry Smith 176*028b6e76SBarry Smith #undef __FUNCT__ 177*028b6e76SBarry Smith #define __FUNCT__ "SNESLineSearchQuadratic_Picard" 178*028b6e76SBarry Smith PetscErrorCode SNESLineSearchQuadratic_Picard(SNES snes,void *lsctx,Vec X,Vec F,Vec Y,PetscReal fnorm,PetscReal dummyXnorm,Vec G,Vec W,PetscReal *dummyYnorm,PetscReal *gnorm,PetscBool *flag) 179*028b6e76SBarry Smith { 180*028b6e76SBarry Smith PetscInt i; 181*028b6e76SBarry Smith PetscReal alphas[3] = {0.0, 0.5, 1.0}; 182*028b6e76SBarry Smith PetscReal norms[3]; 183*028b6e76SBarry Smith PetscReal alpha,a,b; 184*028b6e76SBarry Smith PetscErrorCode ierr; 185*028b6e76SBarry Smith SNES_Picard *neP = (SNES_Picard *) snes->data; 186*028b6e76SBarry Smith 187*028b6e76SBarry Smith PetscFunctionBegin; 188*028b6e76SBarry Smith norms[0] = fnorm; 189*028b6e76SBarry Smith for(i=1; i < 3; ++i) { 190*028b6e76SBarry Smith ierr = VecWAXPY(W, alphas[i], Y, X);CHKERRQ(ierr); /* W = X^n - \alpha Y */ 191*028b6e76SBarry Smith ierr = SNESComputeFunction(snes, W, F);CHKERRQ(ierr); 192*028b6e76SBarry Smith ierr = VecNorm(F, NORM_2, &norms[i]);CHKERRQ(ierr); 193*028b6e76SBarry Smith } 194*028b6e76SBarry Smith for(i = 0; i < 3; ++i) { 195*028b6e76SBarry Smith norms[i] = PetscSqr(norms[i]); 196*028b6e76SBarry Smith } 197*028b6e76SBarry Smith /* Fit a quadratic: 198*028b6e76SBarry Smith If we have x_{0,1,2} = 0, x_1, x_2 which generate norms y_{0,1,2} 199*028b6e76SBarry Smith 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) 200*028b6e76SBarry Smith 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) 201*028b6e76SBarry Smith c = y_0 202*028b6e76SBarry Smith x_min = -b/2a 203*028b6e76SBarry Smith 204*028b6e76SBarry Smith If we let x_{0,1,2} = 0, 0.5, 1.0 205*028b6e76SBarry Smith a = 2 y_2 - 4 y_1 + 2 y_0 206*028b6e76SBarry Smith b = -y_2 + 4 y_1 - 3 y_0 207*028b6e76SBarry Smith c = y_0 208*028b6e76SBarry Smith */ 209*028b6e76SBarry Smith 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])); 210*028b6e76SBarry Smith 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]); 211*028b6e76SBarry Smith /* Check for positive a (concave up) */ 212*028b6e76SBarry Smith if (a >= 0.0) { 213*028b6e76SBarry Smith alpha = -b/(2.0*a); 214*028b6e76SBarry Smith alpha = PetscMin(alpha, alphas[2]); 215*028b6e76SBarry Smith alpha = PetscMax(alpha, alphas[0]); 216*028b6e76SBarry Smith } else { 217*028b6e76SBarry Smith alpha = 1.0; 218*028b6e76SBarry Smith } 219*028b6e76SBarry Smith if (neP->monitor) { 220*028b6e76SBarry Smith ierr = PetscViewerASCIIAddTab(neP->monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 221*028b6e76SBarry Smith ierr = PetscViewerASCIIPrintf(neP->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); 222*028b6e76SBarry Smith ierr = PetscViewerASCIISubtractTab(neP->monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 223*028b6e76SBarry Smith } 224*028b6e76SBarry Smith ierr = VecAXPY(X, alpha, Y);CHKERRQ(ierr); 225*028b6e76SBarry Smith if (alpha != 1.0) { 226*028b6e76SBarry Smith ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 227*028b6e76SBarry Smith ierr = VecNorm(F, NORM_2, gnorm);CHKERRQ(ierr); 228*028b6e76SBarry Smith } else { 229*028b6e76SBarry Smith *gnorm = PetscSqrtReal(norms[2]); 230*028b6e76SBarry Smith } 231*028b6e76SBarry Smith if (alpha == 0.0) *flag = PETSC_FALSE; 232*028b6e76SBarry Smith else *flag = PETSC_TRUE; 233*028b6e76SBarry Smith PetscFunctionReturn(0); 234*028b6e76SBarry Smith } 235*028b6e76SBarry Smith 236*028b6e76SBarry Smith /* 237*028b6e76SBarry Smith SNESSolve_Picard - Solves a nonlinear system with the Picard method. 238*028b6e76SBarry Smith 239*028b6e76SBarry Smith Input Parameters: 240*028b6e76SBarry Smith . snes - the SNES context 241*028b6e76SBarry Smith 242*028b6e76SBarry Smith Output Parameter: 243*028b6e76SBarry Smith . outits - number of iterations until termination 244*028b6e76SBarry Smith 245*028b6e76SBarry Smith Application Interface Routine: SNESSolve() 246*028b6e76SBarry Smith */ 247*028b6e76SBarry Smith #undef __FUNCT__ 248*028b6e76SBarry Smith #define __FUNCT__ "SNESSolve_Picard" 249*028b6e76SBarry Smith PetscErrorCode SNESSolve_Picard(SNES snes) 250*028b6e76SBarry Smith { 251*028b6e76SBarry Smith SNES_Picard *neP = (SNES_Picard *) snes->data; 252*028b6e76SBarry Smith Vec X, Y, F, W; 253*028b6e76SBarry Smith PetscReal fnorm; 254*028b6e76SBarry Smith PetscInt maxits, i; 255*028b6e76SBarry Smith PetscErrorCode ierr; 256*028b6e76SBarry Smith SNESConvergedReason reason; 257*028b6e76SBarry Smith 258*028b6e76SBarry Smith PetscFunctionBegin; 259*028b6e76SBarry Smith snes->reason = SNES_CONVERGED_ITERATING; 260*028b6e76SBarry Smith 261*028b6e76SBarry Smith maxits = snes->max_its; /* maximum number of iterations */ 262*028b6e76SBarry Smith X = snes->vec_sol; /* X^n */ 263*028b6e76SBarry Smith Y = snes->vec_sol_update; /* \tilde X */ 264*028b6e76SBarry Smith F = snes->vec_func; /* residual vector */ 265*028b6e76SBarry Smith W = snes->work[0]; /* work vector */ 266*028b6e76SBarry Smith 267*028b6e76SBarry Smith ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 268*028b6e76SBarry Smith snes->iter = 0; 269*028b6e76SBarry Smith snes->norm = 0.; 270*028b6e76SBarry Smith ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 271*028b6e76SBarry Smith ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 272*028b6e76SBarry Smith if (snes->domainerror) { 273*028b6e76SBarry Smith snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 274*028b6e76SBarry Smith PetscFunctionReturn(0); 275*028b6e76SBarry Smith } 276*028b6e76SBarry Smith ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 277*028b6e76SBarry Smith if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Infinite or not-a-number generated in norm"); 278*028b6e76SBarry Smith ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 279*028b6e76SBarry Smith snes->norm = fnorm; 280*028b6e76SBarry Smith ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 281*028b6e76SBarry Smith SNESLogConvHistory(snes,fnorm,0); 282*028b6e76SBarry Smith ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 283*028b6e76SBarry Smith 284*028b6e76SBarry Smith /* set parameter for default relative tolerance convergence test */ 285*028b6e76SBarry Smith snes->ttol = fnorm*snes->rtol; 286*028b6e76SBarry Smith /* test convergence */ 287*028b6e76SBarry Smith ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 288*028b6e76SBarry Smith if (snes->reason) PetscFunctionReturn(0); 289*028b6e76SBarry Smith 290*028b6e76SBarry Smith for(i = 0; i < maxits; i++) { 291*028b6e76SBarry Smith PetscBool lsSuccess = PETSC_TRUE; 292*028b6e76SBarry Smith PetscReal dummyNorm; 293*028b6e76SBarry Smith 294*028b6e76SBarry Smith /* Call general purpose update function */ 295*028b6e76SBarry Smith if (snes->ops->update) { 296*028b6e76SBarry Smith ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 297*028b6e76SBarry Smith } 298*028b6e76SBarry Smith if (!snes->pc) { 299*028b6e76SBarry Smith ierr = VecCopy(F,Y);CHKERRQ(ierr); 300*028b6e76SBarry Smith ierr = VecScale(Y,-1.0);CHKERRQ(ierr); 301*028b6e76SBarry Smith } else { 302*028b6e76SBarry Smith ierr = VecCopy(X,Y);CHKERRQ(ierr); 303*028b6e76SBarry Smith ierr = SNESSolve(snes->pc, 0, Y);CHKERRQ(ierr); 304*028b6e76SBarry Smith ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 305*028b6e76SBarry Smith if (reason < 0) { 306*028b6e76SBarry Smith snes->reason = SNES_DIVERGED_INNER; 307*028b6e76SBarry Smith PetscFunctionReturn(0); 308*028b6e76SBarry Smith } 309*028b6e76SBarry Smith ierr = VecAXPY(Y,-1.0,X);CHKERRQ(ierr); 310*028b6e76SBarry Smith } 311*028b6e76SBarry Smith 312*028b6e76SBarry Smith ierr = (*neP->LineSearch)(snes, neP->lsP, X, F, Y, fnorm, 0.0, 0, W, &dummyNorm, &fnorm, &lsSuccess);CHKERRQ(ierr); 313*028b6e76SBarry Smith if (!lsSuccess) { 314*028b6e76SBarry Smith if (++snes->numFailures >= snes->maxFailures) { 315*028b6e76SBarry Smith snes->reason = SNES_DIVERGED_LINE_SEARCH; 316*028b6e76SBarry Smith break; 317*028b6e76SBarry Smith } 318*028b6e76SBarry Smith } 319*028b6e76SBarry Smith if (snes->nfuncs >= snes->max_funcs) { 320*028b6e76SBarry Smith snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 321*028b6e76SBarry Smith break; 322*028b6e76SBarry Smith } 323*028b6e76SBarry Smith if (snes->domainerror) { 324*028b6e76SBarry Smith snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 325*028b6e76SBarry Smith PetscFunctionReturn(0); 326*028b6e76SBarry Smith } 327*028b6e76SBarry Smith /* Monitor convergence */ 328*028b6e76SBarry Smith ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 329*028b6e76SBarry Smith snes->iter = i+1; 330*028b6e76SBarry Smith snes->norm = fnorm; 331*028b6e76SBarry Smith ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 332*028b6e76SBarry Smith SNESLogConvHistory(snes,snes->norm,0); 333*028b6e76SBarry Smith ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 334*028b6e76SBarry Smith /* Test for convergence */ 335*028b6e76SBarry Smith ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 336*028b6e76SBarry Smith if (snes->reason) break; 337*028b6e76SBarry Smith } 338*028b6e76SBarry Smith if (i == maxits) { 339*028b6e76SBarry Smith ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr); 340*028b6e76SBarry Smith if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 341*028b6e76SBarry Smith } 342*028b6e76SBarry Smith PetscFunctionReturn(0); 343*028b6e76SBarry Smith } 344*028b6e76SBarry Smith 345*028b6e76SBarry Smith typedef PetscErrorCode (*FCN1)(SNES,Vec,Vec,void*,PetscBool *); /* force argument to next function to not be extern C*/ 346*028b6e76SBarry Smith EXTERN_C_BEGIN 347*028b6e76SBarry Smith #undef __FUNCT__ 348*028b6e76SBarry Smith #define __FUNCT__ "SNESLineSearchSetPreCheck_Picard" 349*028b6e76SBarry Smith PetscErrorCode SNESLineSearchSetPreCheck_Picard(SNES snes, FCN1 func, void *checkctx) 350*028b6e76SBarry Smith { 351*028b6e76SBarry Smith PetscFunctionBegin; 352*028b6e76SBarry Smith ((SNES_Picard *)(snes->data))->precheckstep = func; 353*028b6e76SBarry Smith ((SNES_Picard *)(snes->data))->precheck = checkctx; 354*028b6e76SBarry Smith PetscFunctionReturn(0); 355*028b6e76SBarry Smith } 356*028b6e76SBarry Smith EXTERN_C_END 357*028b6e76SBarry Smith 358*028b6e76SBarry Smith typedef PetscErrorCode (*FCN2)(SNES,void*,Vec,Vec,Vec,PetscReal,PetscReal,Vec,Vec,PetscReal*,PetscReal*,PetscBool *); /* force argument to next function to not be extern C*/ 359*028b6e76SBarry Smith EXTERN_C_BEGIN 360*028b6e76SBarry Smith #undef __FUNCT__ 361*028b6e76SBarry Smith #define __FUNCT__ "SNESLineSearchSet_Picard" 362*028b6e76SBarry Smith PetscErrorCode SNESLineSearchSet_Picard(SNES snes, FCN2 func, void *lsctx) 363*028b6e76SBarry Smith { 364*028b6e76SBarry Smith PetscFunctionBegin; 365*028b6e76SBarry Smith ((SNES_Picard *)(snes->data))->LineSearch = func; 366*028b6e76SBarry Smith ((SNES_Picard *)(snes->data))->lsP = lsctx; 367*028b6e76SBarry Smith PetscFunctionReturn(0); 368*028b6e76SBarry Smith } 369*028b6e76SBarry Smith EXTERN_C_END 370*028b6e76SBarry Smith 371*028b6e76SBarry Smith typedef PetscErrorCode (*FCN3)(SNES,Vec,Vec,Vec,void*,PetscBool *,PetscBool *); /* force argument to next function to not be extern C*/ 372*028b6e76SBarry Smith EXTERN_C_BEGIN 373*028b6e76SBarry Smith #undef __FUNCT__ 374*028b6e76SBarry Smith #define __FUNCT__ "SNESLineSearchSetPostCheck_Picard" 375*028b6e76SBarry Smith PetscErrorCode SNESLineSearchSetPostCheck_Picard(SNES snes, FCN3 func, void *checkctx) 376*028b6e76SBarry Smith { 377*028b6e76SBarry Smith PetscFunctionBegin; 378*028b6e76SBarry Smith ((SNES_Picard *)(snes->data))->postcheckstep = func; 379*028b6e76SBarry Smith ((SNES_Picard *)(snes->data))->postcheck = checkctx; 380*028b6e76SBarry Smith PetscFunctionReturn(0); 381*028b6e76SBarry Smith } 382*028b6e76SBarry Smith EXTERN_C_END 383*028b6e76SBarry Smith 384*028b6e76SBarry Smith /*MC 385*028b6e76SBarry Smith SNESPICARD - Picard nonlinear solver that uses successive substitutions 386*028b6e76SBarry Smith 387*028b6e76SBarry Smith Level: beginner 388*028b6e76SBarry Smith 389*028b6e76SBarry Smith Options Database: 390*028b6e76SBarry Smith + -snes_ls_damping - damping factor to apply to F(x) (used only if -snes_ls is basic or basicnonorms) 391*028b6e76SBarry Smith - -snes_ls <basic,basicnormnorms,quadratic> 392*028b6e76SBarry Smith 393*028b6e76SBarry Smith Notes: Solves F(x) - b = 0 using x^{n+1} = x^{n} - lambda (F(x^n) - b) where lambda is obtained either SNESLineSearchSetDamping(), -snes_damping or 394*028b6e76SBarry Smith a line search. 395*028b6e76SBarry Smith 396*028b6e76SBarry Smith This uses no derivative information thus will be much slower then Newton's method obtained with -snes_type ls 397*028b6e76SBarry Smith 398*028b6e76SBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESLS, SNESTR 399*028b6e76SBarry Smith M*/ 400*028b6e76SBarry Smith EXTERN_C_BEGIN 401*028b6e76SBarry Smith #undef __FUNCT__ 402*028b6e76SBarry Smith #define __FUNCT__ "SNESCreate_Picard" 403*028b6e76SBarry Smith PetscErrorCode SNESCreate_Picard(SNES snes) 404*028b6e76SBarry Smith { 405*028b6e76SBarry Smith SNES_Picard *neP; 406*028b6e76SBarry Smith PetscErrorCode ierr; 407*028b6e76SBarry Smith 408*028b6e76SBarry Smith PetscFunctionBegin; 409*028b6e76SBarry Smith snes->ops->destroy = SNESDestroy_Picard; 410*028b6e76SBarry Smith snes->ops->setup = SNESSetUp_Picard; 411*028b6e76SBarry Smith snes->ops->setfromoptions = SNESSetFromOptions_Picard; 412*028b6e76SBarry Smith snes->ops->view = SNESView_Picard; 413*028b6e76SBarry Smith snes->ops->solve = SNESSolve_Picard; 414*028b6e76SBarry Smith snes->ops->reset = SNESReset_Picard; 415*028b6e76SBarry Smith 416*028b6e76SBarry Smith snes->usesksp = PETSC_FALSE; 417*028b6e76SBarry Smith 418*028b6e76SBarry Smith ierr = PetscNewLog(snes, SNES_Picard, &neP);CHKERRQ(ierr); 419*028b6e76SBarry Smith snes->data = (void*) neP; 420*028b6e76SBarry Smith neP->maxstep = 1.e8; 421*028b6e76SBarry Smith neP->steptol = 1.e-12; 422*028b6e76SBarry Smith neP->type = SNES_LS_QUADRATIC; 423*028b6e76SBarry Smith neP->damping = 1.0; 424*028b6e76SBarry Smith neP->LineSearch = SNESLineSearchQuadratic_Picard; 425*028b6e76SBarry Smith neP->lsP = PETSC_NULL; 426*028b6e76SBarry Smith neP->postcheckstep = PETSC_NULL; 427*028b6e76SBarry Smith neP->postcheck = PETSC_NULL; 428*028b6e76SBarry Smith neP->precheckstep = PETSC_NULL; 429*028b6e76SBarry Smith neP->precheck = PETSC_NULL; 430*028b6e76SBarry Smith 431*028b6e76SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","SNESLineSearchSetMonitor_Picard",SNESLineSearchSetMonitor_Picard);CHKERRQ(ierr); 432*028b6e76SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","SNESLineSearchSet_Picard",SNESLineSearchSet_Picard);CHKERRQ(ierr); 433*028b6e76SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetPostCheck_C","SNESLineSearchSetPostCheck_Picard",SNESLineSearchSetPostCheck_Picard);CHKERRQ(ierr); 434*028b6e76SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetPreCheck_C","SNESLineSearchSetPreCheck_Picard",SNESLineSearchSetPreCheck_Picard);CHKERRQ(ierr); 435*028b6e76SBarry Smith PetscFunctionReturn(0); 436*028b6e76SBarry Smith } 437*028b6e76SBarry Smith EXTERN_C_END 438