Actual source code: picard.c
1: #define PETSCSNES_DLL
3: #include src/snes/impls/picard/picard.h
5: /*
6: SNESDestroy_Picard - Destroys the private SNES_Picard context that was created with SNESCreate_Picard().
8: Input Parameter:
9: . snes - the SNES context
11: Application Interface Routine: SNESDestroy()
12: */
15: PetscErrorCode SNESDestroy_Picard(SNES snes)
16: {
20: if (snes->vec_sol_update) {
21: VecDestroy(snes->vec_sol_update);
22: }
23: PetscFree(snes->data);
24: return(0);
25: }
27: /*
28: SNESSetUp_Picard - Sets up the internal data structures for the later use
29: of the SNESPICARD nonlinear solver.
31: Input Parameters:
32: + snes - the SNES context
33: - x - the solution vector
35: Application Interface Routine: SNESSetUp()
36: */
39: PetscErrorCode SNESSetUp_Picard(SNES snes)
40: {
44: VecDuplicate(snes->vec_sol, &snes->vec_sol_update);
45: return(0);
46: }
48: /*
49: SNESSetFromOptions_Picard - Sets various parameters for the SNESLS method.
51: Input Parameter:
52: . snes - the SNES context
54: Application Interface Routine: SNESSetFromOptions()
55: */
58: static PetscErrorCode SNESSetFromOptions_Picard(SNES snes)
59: {
60: SNES_Picard *ls = (SNES_Picard *)snes->data;
61: const char *types[] = {"basic"};
62: PetscInt indx;
63: PetscTruth flg;
67: PetscOptionsHead("SNES Picard options");
68: PetscOptionsEList("-snes_picard","Picard Type","SNESLineSearchSet",types,1,"basic",&indx,&flg);
69: if (flg) {
70: ls->type = indx;
71: }
72: PetscOptionsTail();
73: return(0);
74: }
76: /*
77: SNESView_Picard - Prints info from the SNESPICARD data structure.
79: Input Parameters:
80: + SNES - the SNES context
81: - viewer - visualization context
83: Application Interface Routine: SNESView()
84: */
87: static PetscErrorCode SNESView_Picard(SNES snes, PetscViewer viewer)
88: {
89: SNES_Picard *ls = (SNES_Picard *)snes->data;
90: const char *cstr;
91: PetscTruth iascii;
95: PetscTypeCompare((PetscObject) viewer, PETSC_VIEWER_ASCII, &iascii);
96: if (iascii) {
97: switch(ls->type) {
98: case 0:
99: cstr = "basic";
100: break;
101: default:
102: cstr = "unknown";
103: }
104: PetscViewerASCIIPrintf(viewer," picard variant: %s\n", cstr);
105: } else {
106: SETERRQ1(PETSC_ERR_SUP, "Viewer type %s not supported for SNES Picard", ((PetscObject)viewer)->type_name);
107: }
108: return(0);
109: }
111: /*
112: SNESSolve_Picard - Solves a nonlinear system with the Picard method.
114: Input Parameters:
115: . snes - the SNES context
117: Output Parameter:
118: . outits - number of iterations until termination
120: Application Interface Routine: SNESSolve()
121: */
124: PetscErrorCode SNESSolve_Picard(SNES snes)
125: {
126: SNES_Picard *neP = (SNES_Picard *) snes->data;
127: Vec X, Y, F;
128: PetscReal alpha = 1.0;
129: PetscReal fnorm;
130: PetscInt maxits, i;
134: snes->reason = SNES_CONVERGED_ITERATING;
136: maxits = snes->max_its; /* maximum number of iterations */
137: X = snes->vec_sol; /* X^n */
138: Y = snes->vec_sol_update; /* \tilde X */
139: F = snes->vec_func; /* residual vector */
141: PetscObjectTakeAccess(snes);
142: snes->iter = 0;
143: snes->norm = 0;
144: PetscObjectGrantAccess(snes);
145: SNESComputeFunction(snes,X,F);
146: if (snes->domainerror) {
147: snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
148: return(0);
149: }
150: VecNorm(F, NORM_2, &fnorm);CHKFPQ(fnorm); /* fnorm <- ||F|| */
151: PetscObjectTakeAccess(snes);
152: snes->norm = fnorm;
153: PetscObjectGrantAccess(snes);
154: SNESLogConvHistory(snes,fnorm,0);
155: SNESMonitor(snes,0,fnorm);
157: /* set parameter for default relative tolerance convergence test */
158: snes->ttol = fnorm*snes->rtol;
159: /* test convergence */
160: (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);
161: if (snes->reason) return(0);
163: for(i = 0; i < maxits; i++) {
164: PetscTruth lsSuccess = PETSC_TRUE;
165: PetscReal dummyNorm;
167: if (0) {
168: /* Update guess Y = X^n - F(X^n) */
169: VecWAXPY(Y, -1.0, F, X);
170: /* X^{n+1} = (1 - \alpha) X^n + \alpha Y */
171: VecAXPBY(X, alpha, 1 - alpha, Y);
172: /* Compute F(X^{new}) */
173: SNESComputeFunction(snes, X, F);
174: VecNorm(F, NORM_2, &fnorm);CHKFPQ(fnorm);
175: } else {
176: (*neP->LineSearch)(snes, PETSC_NULL/*neP->lsP*/, X, F, F, F, X, fnorm, &dummyNorm, &fnorm, &lsSuccess);
177: }
178: if (!lsSuccess) {
179: if (++snes->numFailures >= snes->maxFailures) {
180: snes->reason = SNES_DIVERGED_LS_FAILURE;
181: break;
182: }
183: }
184: if (snes->nfuncs >= snes->max_funcs) {
185: snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
186: break;
187: }
188: if (snes->domainerror) {
189: snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
190: return(0);
191: }
192: /* Monitor convergence */
193: PetscObjectTakeAccess(snes);
194: snes->iter = i+1;
195: snes->norm = fnorm;
196: PetscObjectGrantAccess(snes);
197: SNESLogConvHistory(snes,snes->norm,0);
198: SNESMonitor(snes,snes->iter,snes->norm);
199: /* Test for convergence */
200: (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);
201: if (snes->reason) break;
202: }
203: if (i == maxits) {
204: PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);
205: if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
206: }
207: return(0);
208: }
214: PetscErrorCode SNESLineSearchSetPreCheck_Picard(SNES snes, FCN1 func, void *checkctx)
215: {
217: ((SNES_Picard *)(snes->data))->precheckstep = func;
218: ((SNES_Picard *)(snes->data))->precheck = checkctx;
219: return(0);
220: }
227: PetscErrorCode SNESLineSearchSet_Picard(SNES snes, FCN2 func, void *lsctx)
228: {
230: ((SNES_Picard *)(snes->data))->LineSearch = func;
231: ((SNES_Picard *)(snes->data))->lsP = lsctx;
232: return(0);
233: }
240: PetscErrorCode SNESLineSearchSetPostCheck_Picard(SNES snes, FCN3 func, void *checkctx)
241: {
243: ((SNES_Picard *)(snes->data))->postcheckstep = func;
244: ((SNES_Picard *)(snes->data))->postcheck = checkctx;
245: return(0);
246: }
249: /*MC
250: SNESPICARD - Picard nonlinear solver that uses successive substitutions
252: Level: beginner
254: .seealso: SNESCreate(), SNES, SNESSetType(), SNESLS, SNESTR
255: M*/
259: PetscErrorCode SNESCreate_Picard(SNES snes)
260: {
261: SNES_Picard *neP;
265: snes->ops->destroy = SNESDestroy_Picard;
266: snes->ops->setup = SNESSetUp_Picard;
267: snes->ops->setfromoptions = SNESSetFromOptions_Picard;
268: snes->ops->view = SNESView_Picard;
269: snes->ops->solve = SNESSolve_Picard;
271: PetscNewLog(snes, SNES_Picard, &neP);
272: snes->data = (void*) neP;
273: neP->type = 0;
274: neP->alpha = 1.e-4;
275: neP->maxstep = 1.e8;
276: neP->steptol = 1.e-12;
277: neP->LineSearch = SNESLineSearchNo;
278: neP->lsP = PETSC_NULL;
279: neP->postcheckstep = PETSC_NULL;
280: neP->postcheck = PETSC_NULL;
281: neP->precheckstep = PETSC_NULL;
282: neP->precheck = PETSC_NULL;
284: PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C",
285: "SNESLineSearchSet_Picard",
286: SNESLineSearchSet_Picard);
287: PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetPostCheck_C",
288: "SNESLineSearchSetPostCheck_Picard",
289: SNESLineSearchSetPostCheck_Picard);
290: PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetPreCheck_C",
291: "SNESLineSearchSetPreCheck_Picard",
292: SNESLineSearchSetPreCheck_Picard);
293: return(0);
294: }