Actual source code: ex1.c
petsc-3.7.7 2017-09-25
2: static char help[] = "Newton's method for a two-variable system, sequential.\n\n" ;
4: /*T
5: Concepts: SNES ^basic example
6: T*/
8: /*
9: Include "petscsnes.h" so that we can use SNES solvers. Note that this
10: file automatically includes:
11: petscsys.h - base PETSc routines petscvec.h - vectors
12: petscmat.h - matrices
13: petscis.h - index sets petscksp.h - Krylov subspace methods
14: petscviewer.h - viewers petscpc.h - preconditioners
15: petscksp.h - linear solvers
16: */
This examples solves either
\begin{equation}
F\genfrac{(}{)}{0pt}{}{x_0}{x_1} = \genfrac{(}{)}{0pt}{}{x^2_0 + x_0 x_1 - 3}{x_0 x_1 + x^2_1 - 6}
\end{equation}
or if the {\tt -hard} options is given
\begin{equation}
F\genfrac{(}{)}{0pt}{}{x_0}{x_1} = \genfrac{(}{)}{0pt}{}{\sin(3 x_0) + x_0}{x_1}
\end{equation}
27: #include <petscsnes.h>
29: /*
30: User-defined routines
31: */
32: extern PetscErrorCode FormJacobian1(SNES ,Vec ,Mat ,Mat ,void*) ;
33: extern PetscErrorCode FormFunction1(SNES ,Vec ,Vec ,void*) ;
34: extern PetscErrorCode FormJacobian2(SNES ,Vec ,Mat ,Mat ,void*) ;
35: extern PetscErrorCode FormFunction2(SNES ,Vec ,Vec ,void*) ;
39: int main(int argc,char **argv)
40: {
41: SNES snes; /* nonlinear solver context */
42: KSP ksp; /* linear solver context */
43: PC pc; /* preconditioner context */
44: Vec x,r; /* solution, residual vectors */
45: Mat J; /* Jacobian matrix */
47: PetscInt its;
48: PetscMPIInt size;
49: PetscScalar pfive = .5,*xx;
50: PetscBool flg;
52: PetscInitialize (&argc,&argv,(char*)0,help);
53: MPI_Comm_size (PETSC_COMM_WORLD ,&size);
54: if (size > 1) SETERRQ (PETSC_COMM_WORLD ,PETSC_ERR_SUP,"Example is only for sequential runs" );
56: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
57: Create nonlinear solver context
58: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
59: SNESCreate (PETSC_COMM_WORLD ,&snes);
61: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
62: Create matrix and vector data structures; set corresponding routines
63: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
64: /*
65: Create vectors for solution and nonlinear function
66: */
67: VecCreate (PETSC_COMM_WORLD ,&x);
68: VecSetSizes (x,PETSC_DECIDE ,2);
69: VecSetFromOptions (x);
70: VecDuplicate (x,&r);
72: /*
73: Create Jacobian matrix data structure
74: */
75: MatCreate (PETSC_COMM_WORLD ,&J);
76: MatSetSizes (J,PETSC_DECIDE ,PETSC_DECIDE ,2,2);
77: MatSetFromOptions (J);
78: MatSetUp (J);
80: PetscOptionsHasName (NULL,NULL,"-hard" ,&flg);
81: if (!flg) {
82: /*
83: Set function evaluation routine and vector.
84: */
85: SNESSetFunction (snes,r,FormFunction1,NULL);
87: /*
88: Set Jacobian matrix data structure and Jacobian evaluation routine
89: */
90: SNESSetJacobian (snes,J,J,FormJacobian1,NULL);
91: } else {
92: SNESSetFunction (snes,r,FormFunction2,NULL);
93: SNESSetJacobian (snes,J,J,FormJacobian2,NULL);
94: }
96: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
97: Customize nonlinear solver; set runtime options
98: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
99: /*
100: Set linear solver defaults for this problem. By extracting the
101: KSP and PC contexts from the SNES context, we can then
102: directly call any KSP and PC routines to set various options.
103: */
104: SNESGetKSP (snes,&ksp);
105: KSPGetPC (ksp,&pc);
106: PCSetType (pc,PCNONE );
107: KSPSetTolerances (ksp,1.e-4,PETSC_DEFAULT ,PETSC_DEFAULT ,20);
109: /*
110: Set SNES /KSP /KSP /PC runtime options, e.g.,
111: -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc>
112: These options will override those specified above as long as
113: SNESSetFromOptions () is called _after_ any other customization
114: routines.
115: */
116: SNESSetFromOptions (snes);
118: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
119: Evaluate initial guess; then solve nonlinear system
120: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
121: if (!flg) {
122: VecSet (x,pfive);
123: } else {
124: VecGetArray (x,&xx);
125: xx[0] = 2.0; xx[1] = 3.0;
126: VecRestoreArray (x,&xx);
127: }
128: /*
129: Note: The user should initialize the vector, x, with the initial guess
130: for the nonlinear solver prior to calling SNESSolve (). In particular,
131: to employ an initial guess of zero, the user should explicitly set
132: this vector to zero by calling VecSet ().
133: */
135: SNESSolve (snes,NULL,x);
136: SNESGetIterationNumber (snes,&its);
137: if (flg) {
138: Vec f;
139: VecView (x,PETSC_VIEWER_STDOUT_WORLD );
140: SNESGetFunction (snes,&f,0,0);
141: VecView (r,PETSC_VIEWER_STDOUT_WORLD );
142: }
144: PetscPrintf (PETSC_COMM_WORLD ,"Number of SNES iterations = %D\n" ,its);
146: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
147: Free work space. All PETSc objects should be destroyed when they
148: are no longer needed.
149: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
151: VecDestroy (&x); VecDestroy (&r);
152: MatDestroy (&J); SNESDestroy (&snes);
153: PetscFinalize ();
154: return 0;
155: }
156: /* ------------------------------------------------------------------- */
159: /*
160: FormFunction1 - Evaluates nonlinear function, F(x).
162: Input Parameters:
163: . snes - the SNES context
164: . x - input vector
165: . ctx - optional user-defined context
167: Output Parameter:
168: . f - function vector
169: */
170: PetscErrorCode FormFunction1(SNES snes,Vec x,Vec f,void *ctx)
171: {
172: PetscErrorCode ierr;
173: const PetscScalar *xx;
174: PetscScalar *ff;
176: /*
177: Get pointers to vector data.
178: - For default PETSc vectors, VecGetArray () returns a pointer to
179: the data array. Otherwise, the routine is implementation dependent.
180: - You MUST call VecRestoreArray () when you no longer need access to
181: the array.
182: */
183: VecGetArrayRead (x,&xx);
184: VecGetArray (f,&ff);
186: /* Compute function */
187: ff[0] = xx[0]*xx[0] + xx[0]*xx[1] - 3.0;
188: ff[1] = xx[0]*xx[1] + xx[1]*xx[1] - 6.0;
190: /* Restore vectors */
191: VecRestoreArrayRead (x,&xx);
192: VecRestoreArray (f,&ff);
193: return 0;
194: }
195: /* ------------------------------------------------------------------- */
198: /*
199: FormJacobian1 - Evaluates Jacobian matrix.
201: Input Parameters:
202: . snes - the SNES context
203: . x - input vector
204: . dummy - optional user-defined context (not used here)
206: Output Parameters:
207: . jac - Jacobian matrix
208: . B - optionally different preconditioning matrix
209: . flag - flag indicating matrix structure
210: */
211: PetscErrorCode FormJacobian1(SNES snes,Vec x,Mat jac,Mat B,void *dummy)
212: {
213: const PetscScalar *xx;
214: PetscScalar A[4];
215: PetscErrorCode ierr;
216: PetscInt idx[2] = {0,1};
218: /*
219: Get pointer to vector data
220: */
221: VecGetArrayRead (x,&xx);
223: /*
224: Compute Jacobian entries and insert into matrix.
225: - Since this is such a small problem, we set all entries for
226: the matrix at once.
227: */
228: A[0] = 2.0*xx[0] + xx[1]; A[1] = xx[0];
229: A[2] = xx[1]; A[3] = xx[0] + 2.0*xx[1];
230: MatSetValues (B,2,idx,2,idx,A,INSERT_VALUES );
232: /*
233: Restore vector
234: */
235: VecRestoreArrayRead (x,&xx);
237: /*
238: Assemble matrix
239: */
240: MatAssemblyBegin (B,MAT_FINAL_ASSEMBLY);
241: MatAssemblyEnd (B,MAT_FINAL_ASSEMBLY);
242: if (jac != B) {
243: MatAssemblyBegin (jac,MAT_FINAL_ASSEMBLY);
244: MatAssemblyEnd (jac,MAT_FINAL_ASSEMBLY);
245: }
246: return 0;
247: }
249: /* ------------------------------------------------------------------- */
252: PetscErrorCode FormFunction2(SNES snes,Vec x,Vec f,void *dummy)
253: {
254: PetscErrorCode ierr;
255: const PetscScalar *xx;
256: PetscScalar *ff;
258: /*
259: Get pointers to vector data.
260: - For default PETSc vectors, VecGetArray () returns a pointer to
261: the data array. Otherwise, the routine is implementation dependent.
262: - You MUST call VecRestoreArray () when you no longer need access to
263: the array.
264: */
265: VecGetArrayRead (x,&xx);
266: VecGetArray (f,&ff);
268: /*
269: Compute function
270: */
271: ff[0] = PetscSinScalar(3.0*xx[0]) + xx[0];
272: ff[1] = xx[1];
274: /*
275: Restore vectors
276: */
277: VecRestoreArrayRead (x,&xx);
278: VecRestoreArray (f,&ff);
279: return 0;
280: }
281: /* ------------------------------------------------------------------- */
284: PetscErrorCode FormJacobian2(SNES snes,Vec x,Mat jac,Mat B,void *dummy)
285: {
286: const PetscScalar *xx;
287: PetscScalar A[4];
288: PetscErrorCode ierr;
289: PetscInt idx[2] = {0,1};
291: /*
292: Get pointer to vector data
293: */
294: VecGetArrayRead (x,&xx);
296: /*
297: Compute Jacobian entries and insert into matrix.
298: - Since this is such a small problem, we set all entries for
299: the matrix at once.
300: */
301: A[0] = 3.0*PetscCosScalar(3.0*xx[0]) + 1.0; A[1] = 0.0;
302: A[2] = 0.0; A[3] = 1.0;
303: MatSetValues (B,2,idx,2,idx,A,INSERT_VALUES );
305: /*
306: Restore vector
307: */
308: VecRestoreArrayRead (x,&xx);
310: /*
311: Assemble matrix
312: */
313: MatAssemblyBegin (B,MAT_FINAL_ASSEMBLY);
314: MatAssemblyEnd (B,MAT_FINAL_ASSEMBLY);
315: if (jac != B) {
316: MatAssemblyBegin (jac,MAT_FINAL_ASSEMBLY);
317: MatAssemblyEnd (jac,MAT_FINAL_ASSEMBLY);
318: }
319: return 0;
320: }