Actual source code: ex2.c
1: /*$Id: ex2.c,v 1.81 2001/03/23 23:24:25 balay Exp $*/
3: static char help[] = "Newton method to solve u'' + u^{2} = f, sequentially.n
4: This example employs a user-defined monitoring routine.nn";
6: /*T
7: Concepts: SNES^basic uniprocessor example
8: Concepts: SNES^setting a user-defined monitoring routine
9: Processors: 1
10: T*/
12: /*
13: Include "petscdraw.h" so that we can use PETSc drawing routines.
14: Include "petscsnes.h" so that we can use SNES solvers. Note that this
15: file automatically includes:
16: petsc.h - base PETSc routines petscvec.h - vectors
17: petscsys.h - system routines petscmat.h - matrices
18: petscis.h - index sets petscksp.h - Krylov subspace methods
19: petscviewer.h - viewers petscpc.h - preconditioners
20: petscsles.h - linear solvers
21: */
23: #include "petscsnes.h"
25: /*
26: User-defined routines
27: */
28: extern int FormJacobian(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
29: extern int FormFunction(SNES,Vec,Vec,void*);
30: extern int FormInitialGuess(Vec);
31: extern int Monitor(SNES,int,double,void *);
33: /*
34: User-defined context for monitoring
35: */
36: typedef struct {
37: PetscViewer viewer;
38: } MonitorCtx;
40: int main(int argc,char **argv)
41: {
42: SNES snes; /* SNES context */
43: Vec x,r,F,U; /* vectors */
44: Mat J; /* Jacobian matrix */
45: MonitorCtx monP; /* monitoring context */
46: int ierr,its,n = 5,i,maxit,maxf,size;
47: Scalar h,xp,v,none = -1.0;
48: double atol,rtol,stol,norm;
50: PetscInitialize(&argc,&argv,(char *)0,help);
51: MPI_Comm_size(PETSC_COMM_WORLD,&size);
52: if (size != 1) SETERRQ(1,"This is a uniprocessor example only!");
53: PetscOptionsGetInt(PETSC_NULL,"-n",&n,PETSC_NULL);
54: h = 1.0/(n-1);
56: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
57: Create nonlinear solver context
58: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
60: SNESCreate(PETSC_COMM_WORLD,SNES_NONLINEAR_EQUATIONS,&snes);
62: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
63: Create vector data structures; set function evaluation routine
64: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
65: /*
66: Note that we form 1 vector from scratch and then duplicate as needed.
67: */
68: VecCreate(PETSC_COMM_WORLD,PETSC_DECIDE,n,&x);
69: VecSetFromOptions(x);
70: VecDuplicate(x,&r);
71: VecDuplicate(x,&F);
72: VecDuplicate(x,&U);
74: /*
75: Set function evaluation routine and vector
76: */
77: SNESSetFunction(snes,r,FormFunction,(void*)F);
80: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
81: Create matrix data structure; set Jacobian evaluation routine
82: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
84: MatCreate(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,n,n,&J);
85: MatSetFromOptions(J);
87: /*
88: Set Jacobian matrix data structure and default Jacobian evaluation
89: routine. User can override with:
90: -snes_fd : default finite differencing approximation of Jacobian
91: -snes_mf : matrix-free Newton-Krylov method with no preconditioning
92: (unless user explicitly sets preconditioner)
93: -snes_mf_operator : form preconditioning matrix as set by the user,
94: but use matrix-free approx for Jacobian-vector
95: products within Newton-Krylov method
96: */
98: SNESSetJacobian(snes,J,J,FormJacobian,PETSC_NULL);
100: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
101: Customize nonlinear solver; set runtime options
102: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
104: /*
105: Set an optional user-defined monitoring routine
106: */
107: PetscViewerDrawOpen(PETSC_COMM_WORLD,0,0,0,0,400,400,&monP.viewer);
108: SNESSetMonitor(snes,Monitor,&monP,0);
110: /*
111: Set names for some vectors to facilitate monitoring (optional)
112: */
113: PetscObjectSetName((PetscObject)x,"Approximate Solution");
114: PetscObjectSetName((PetscObject)U,"Exact Solution");
116: /*
117: Set SNES/SLES/KSP/PC runtime options, e.g.,
118: -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc>
119: */
120: SNESSetFromOptions(snes);
122: /*
123: Print parameters used for convergence testing (optional) ... just
124: to demonstrate this routine; this information is also printed with
125: the option -snes_view
126: */
127: SNESGetTolerances(snes,&atol,&rtol,&stol,&maxit,&maxf);
128: PetscPrintf(PETSC_COMM_WORLD,"atol=%g, rtol=%g, stol=%g, maxit=%d, maxf=%dn",atol,rtol,stol,maxit,maxf);
130: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
131: Initialize application:
132: Store right-hand-side of PDE and exact solution
133: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
135: xp = 0.0;
136: for (i=0; i<n; i++) {
137: v = 6.0*xp + PetscPowScalar(xp+1.e-12,6.0); /* +1.e-12 is to prevent 0^6 */
138: VecSetValues(F,1,&i,&v,INSERT_VALUES);
139: v= xp*xp*xp;
140: VecSetValues(U,1,&i,&v,INSERT_VALUES);
141: xp += h;
142: }
144: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
145: Evaluate initial guess; then solve nonlinear system
146: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
147: /*
148: Note: The user should initialize the vector, x, with the initial guess
149: for the nonlinear solver prior to calling SNESSolve(). In particular,
150: to employ an initial guess of zero, the user should explicitly set
151: this vector to zero by calling VecSet().
152: */
153: FormInitialGuess(x);
154: SNESSolve(snes,x,&its);
155: PetscPrintf(PETSC_COMM_WORLD,"number of Newton iterations = %dnn",its);
157: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
158: Check solution and clean up
159: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
161: /*
162: Check the error
163: */
164: VecAXPY(&none,U,x);
165: ierr = VecNorm(x,NORM_2,&norm);
166: PetscPrintf(PETSC_COMM_WORLD,"Norm of error %A, Iterations %dn",norm,its);
169: /*
170: Free work space. All PETSc objects should be destroyed when they
171: are no longer needed.
172: */
173: VecDestroy(x); VecDestroy(r);
174: VecDestroy(U); VecDestroy(F);
175: MatDestroy(J); SNESDestroy(snes);
176: PetscViewerDestroy(monP.viewer);
177: PetscFinalize();
179: return 0;
180: }
181: /* ------------------------------------------------------------------- */
182: /*
183: FormInitialGuess - Computes initial guess.
185: Input/Output Parameter:
186: . x - the solution vector
187: */
188: int FormInitialGuess(Vec x)
189: {
190: int ierr;
191: Scalar pfive = .50;
192: VecSet(&pfive,x);
193: return 0;
194: }
195: /* ------------------------------------------------------------------- */
196: /*
197: FormFunction - Evaluates nonlinear function, F(x).
199: Input Parameters:
200: . snes - the SNES context
201: . x - input vector
202: . ctx - optional user-defined context, as set by SNESSetFunction()
204: Output Parameter:
205: . f - function vector
207: Note:
208: The user-defined context can contain any application-specific data
209: needed for the function evaluation (such as various parameters, work
210: vectors, and grid information). In this program the context is just
211: a vector containing the right-hand-side of the discretized PDE.
212: */
214: int FormFunction(SNES snes,Vec x,Vec f,void *ctx)
215: {
216: Vec g = (Vec)ctx;
217: Scalar *xx,*ff,*gg,d;
218: int i,ierr,n;
220: /*
221: Get pointers to vector data.
222: - For default PETSc vectors, VecGetArray() returns a pointer to
223: the data array. Otherwise, the routine is implementation dependent.
224: - You MUST call VecRestoreArray() when you no longer need access to
225: the array.
226: */
227: VecGetArray(x,&xx);
228: VecGetArray(f,&ff);
229: VecGetArray(g,&gg);
231: /*
232: Compute function
233: */
234: VecGetSize(x,&n);
235: d = (double)(n - 1); d = d*d;
236: ff[0] = xx[0];
237: for (i=1; i<n-1; i++) {
238: ff[i] = d*(xx[i-1] - 2.0*xx[i] + xx[i+1]) + xx[i]*xx[i] - gg[i];
239: }
240: ff[n-1] = xx[n-1] - 1.0;
242: /*
243: Restore vectors
244: */
245: VecRestoreArray(x,&xx);
246: VecRestoreArray(f,&ff);
247: VecRestoreArray(g,&gg);
248: return 0;
249: }
250: /* ------------------------------------------------------------------- */
251: /*
252: FormJacobian - Evaluates Jacobian matrix.
254: Input Parameters:
255: . snes - the SNES context
256: . x - input vector
257: . dummy - optional user-defined context (not used here)
259: Output Parameters:
260: . jac - Jacobian matrix
261: . B - optionally different preconditioning matrix
262: . flag - flag indicating matrix structure
263: */
265: int FormJacobian(SNES snes,Vec x,Mat *jac,Mat *B,MatStructure*flag,void *dummy)
266: {
267: Scalar *xx,A[3],d;
268: int i,n,j[3],ierr;
270: /*
271: Get pointer to vector data
272: */
273: VecGetArray(x,&xx);
275: /*
276: Compute Jacobian entries and insert into matrix.
277: - Note that in this case we set all elements for a particular
278: row at once.
279: */
280: VecGetSize(x,&n);
281: d = (double)(n - 1); d = d*d;
283: /*
284: Interior grid points
285: */
286: for (i=1; i<n-1; i++) {
287: j[0] = i - 1; j[1] = i; j[2] = i + 1;
288: A[0] = A[2] = d; A[1] = -2.0*d + 2.0*xx[i];
289: MatSetValues(*jac,1,&i,3,j,A,INSERT_VALUES);
290: }
292: /*
293: Boundary points
294: */
295: i = 0; A[0] = 1.0;
296: MatSetValues(*jac,1,&i,1,&i,A,INSERT_VALUES);
297: i = n-1; A[0] = 1.0;
298: MatSetValues(*jac,1,&i,1,&i,A,INSERT_VALUES);
300: /*
301: Restore vector
302: */
303: VecRestoreArray(x,&xx);
305: /*
306: Assemble matrix
307: */
308: MatAssemblyBegin(*jac,MAT_FINAL_ASSEMBLY);
309: MatAssemblyEnd(*jac,MAT_FINAL_ASSEMBLY);
311: return 0;
312: }
313: /* ------------------------------------------------------------------- */
314: /*
315: Monitor - User-defined monitoring routine that views the
316: current iterate with an x-window plot.
318: Input Parameters:
319: snes - the SNES context
320: its - iteration number
321: norm - 2-norm function value (may be estimated)
322: ctx - optional user-defined context for private data for the
323: monitor routine, as set by SNESSetMonitor()
325: Note:
326: See the manpage for PetscViewerDrawOpen() for useful runtime options,
327: such as -nox to deactivate all x-window output.
328: */
329: int Monitor(SNES snes,int its,double fnorm,void *ctx)
330: {
331: int ierr;
332: MonitorCtx *monP = (MonitorCtx*) ctx;
333: Vec x;
335: PetscPrintf(PETSC_COMM_WORLD,"iter = %d, SNES Function norm %gn",its,fnorm);
336: SNESGetSolution(snes,&x);
337: VecView(x,monP->viewer);
338: return 0;
339: }