Actual source code: ex1.c
2: static char help[] = "Newton's method for a two-variable system, sequential.\n\n";
4: /*
5: Include "petscsnes.h" so that we can use SNES solvers. Note that this
6: file automatically includes:
7: petscsys.h - base PETSc routines petscvec.h - vectors
8: petscmat.h - matrices
9: petscis.h - index sets petscksp.h - Krylov subspace methods
10: petscviewer.h - viewers petscpc.h - preconditioners
11: petscksp.h - linear solvers
12: */
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}
23: #include <petscsnes.h>
25: /*
26: User-defined routines
27: */
28: extern PetscErrorCode FormJacobian1(SNES,Vec,Mat,Mat,void*);
29: extern PetscErrorCode FormFunction1(SNES,Vec,Vec,void*);
30: extern PetscErrorCode FormJacobian2(SNES,Vec,Mat,Mat,void*);
31: extern PetscErrorCode FormFunction2(SNES,Vec,Vec,void*);
33: int main(int argc,char **argv)
34: {
35: SNES snes; /* nonlinear solver context */
36: KSP ksp; /* linear solver context */
37: PC pc; /* preconditioner context */
38: Vec x,r; /* solution, residual vectors */
39: Mat J; /* Jacobian matrix */
40: PetscMPIInt size;
41: PetscScalar pfive = .5,*xx;
42: PetscBool flg;
44: PetscInitialize(&argc,&argv,(char*)0,help);
45: MPI_Comm_size(PETSC_COMM_WORLD,&size);
48: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
49: Create nonlinear solver context
50: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
51: SNESCreate(PETSC_COMM_WORLD,&snes);
53: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
54: Create matrix and vector data structures; set corresponding routines
55: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
56: /*
57: Create vectors for solution and nonlinear function
58: */
59: VecCreate(PETSC_COMM_WORLD,&x);
60: VecSetSizes(x,PETSC_DECIDE,2);
61: VecSetFromOptions(x);
62: VecDuplicate(x,&r);
64: /*
65: Create Jacobian matrix data structure
66: */
67: MatCreate(PETSC_COMM_WORLD,&J);
68: MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,2,2);
69: MatSetFromOptions(J);
70: MatSetUp(J);
72: PetscOptionsHasName(NULL,NULL,"-hard",&flg);
73: if (!flg) {
74: /*
75: Set function evaluation routine and vector.
76: */
77: SNESSetFunction(snes,r,FormFunction1,NULL);
79: /*
80: Set Jacobian matrix data structure and Jacobian evaluation routine
81: */
82: SNESSetJacobian(snes,J,J,FormJacobian1,NULL);
83: } else {
84: SNESSetFunction(snes,r,FormFunction2,NULL);
85: SNESSetJacobian(snes,J,J,FormJacobian2,NULL);
86: }
88: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
89: Customize nonlinear solver; set runtime options
90: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
91: /*
92: Set linear solver defaults for this problem. By extracting the
93: KSP and PC contexts from the SNES context, we can then
94: directly call any KSP and PC routines to set various options.
95: */
96: SNESGetKSP(snes,&ksp);
97: KSPGetPC(ksp,&pc);
98: PCSetType(pc,PCNONE);
99: KSPSetTolerances(ksp,1.e-4,PETSC_DEFAULT,PETSC_DEFAULT,20);
101: /*
102: Set SNES/KSP/KSP/PC runtime options, e.g.,
103: -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc>
104: These options will override those specified above as long as
105: SNESSetFromOptions() is called _after_ any other customization
106: routines.
107: */
108: SNESSetFromOptions(snes);
110: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
111: Evaluate initial guess; then solve nonlinear system
112: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
113: if (!flg) {
114: VecSet(x,pfive);
115: } else {
116: VecGetArray(x,&xx);
117: xx[0] = 2.0; xx[1] = 3.0;
118: VecRestoreArray(x,&xx);
119: }
120: /*
121: Note: The user should initialize the vector, x, with the initial guess
122: for the nonlinear solver prior to calling SNESSolve(). In particular,
123: to employ an initial guess of zero, the user should explicitly set
124: this vector to zero by calling VecSet().
125: */
127: SNESSolve(snes,NULL,x);
128: if (flg) {
129: Vec f;
130: VecView(x,PETSC_VIEWER_STDOUT_WORLD);
131: SNESGetFunction(snes,&f,0,0);
132: VecView(r,PETSC_VIEWER_STDOUT_WORLD);
133: }
135: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
136: Free work space. All PETSc objects should be destroyed when they
137: are no longer needed.
138: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
140: VecDestroy(&x)); PetscCall(VecDestroy(&r);
141: MatDestroy(&J)); PetscCall(SNESDestroy(&snes);
142: PetscFinalize();
143: return 0;
144: }
145: /* ------------------------------------------------------------------- */
146: /*
147: FormFunction1 - Evaluates nonlinear function, F(x).
149: Input Parameters:
150: . snes - the SNES context
151: . x - input vector
152: . ctx - optional user-defined context
154: Output Parameter:
155: . f - function vector
156: */
157: PetscErrorCode FormFunction1(SNES snes,Vec x,Vec f,void *ctx)
158: {
159: const PetscScalar *xx;
160: PetscScalar *ff;
162: /*
163: Get pointers to vector data.
164: - For default PETSc vectors, VecGetArray() returns a pointer to
165: the data array. Otherwise, the routine is implementation dependent.
166: - You MUST call VecRestoreArray() when you no longer need access to
167: the array.
168: */
169: VecGetArrayRead(x,&xx);
170: VecGetArray(f,&ff);
172: /* Compute function */
173: ff[0] = xx[0]*xx[0] + xx[0]*xx[1] - 3.0;
174: ff[1] = xx[0]*xx[1] + xx[1]*xx[1] - 6.0;
176: /* Restore vectors */
177: VecRestoreArrayRead(x,&xx);
178: VecRestoreArray(f,&ff);
179: return 0;
180: }
181: /* ------------------------------------------------------------------- */
182: /*
183: FormJacobian1 - Evaluates Jacobian matrix.
185: Input Parameters:
186: . snes - the SNES context
187: . x - input vector
188: . dummy - optional user-defined context (not used here)
190: Output Parameters:
191: . jac - Jacobian matrix
192: . B - optionally different preconditioning matrix
193: . flag - flag indicating matrix structure
194: */
195: PetscErrorCode FormJacobian1(SNES snes,Vec x,Mat jac,Mat B,void *dummy)
196: {
197: const PetscScalar *xx;
198: PetscScalar A[4];
199: PetscInt idx[2] = {0,1};
201: /*
202: Get pointer to vector data
203: */
204: VecGetArrayRead(x,&xx);
206: /*
207: Compute Jacobian entries and insert into matrix.
208: - Since this is such a small problem, we set all entries for
209: the matrix at once.
210: */
211: A[0] = 2.0*xx[0] + xx[1]; A[1] = xx[0];
212: A[2] = xx[1]; A[3] = xx[0] + 2.0*xx[1];
213: MatSetValues(B,2,idx,2,idx,A,INSERT_VALUES);
215: /*
216: Restore vector
217: */
218: VecRestoreArrayRead(x,&xx);
220: /*
221: Assemble matrix
222: */
223: MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
224: MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
225: if (jac != B) {
226: MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);
227: MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);
228: }
229: return 0;
230: }
232: /* ------------------------------------------------------------------- */
233: PetscErrorCode FormFunction2(SNES snes,Vec x,Vec f,void *dummy)
234: {
235: const PetscScalar *xx;
236: PetscScalar *ff;
238: /*
239: Get pointers to vector data.
240: - For default PETSc vectors, VecGetArray() returns a pointer to
241: the data array. Otherwise, the routine is implementation dependent.
242: - You MUST call VecRestoreArray() when you no longer need access to
243: the array.
244: */
245: VecGetArrayRead(x,&xx);
246: VecGetArray(f,&ff);
248: /*
249: Compute function
250: */
251: ff[0] = PetscSinScalar(3.0*xx[0]) + xx[0];
252: ff[1] = xx[1];
254: /*
255: Restore vectors
256: */
257: VecRestoreArrayRead(x,&xx);
258: VecRestoreArray(f,&ff);
259: return 0;
260: }
261: /* ------------------------------------------------------------------- */
262: PetscErrorCode FormJacobian2(SNES snes,Vec x,Mat jac,Mat B,void *dummy)
263: {
264: const PetscScalar *xx;
265: PetscScalar A[4];
266: PetscInt idx[2] = {0,1};
268: /*
269: Get pointer to vector data
270: */
271: VecGetArrayRead(x,&xx);
273: /*
274: Compute Jacobian entries and insert into matrix.
275: - Since this is such a small problem, we set all entries for
276: the matrix at once.
277: */
278: A[0] = 3.0*PetscCosScalar(3.0*xx[0]) + 1.0; A[1] = 0.0;
279: A[2] = 0.0; A[3] = 1.0;
280: MatSetValues(B,2,idx,2,idx,A,INSERT_VALUES);
282: /*
283: Restore vector
284: */
285: VecRestoreArrayRead(x,&xx);
287: /*
288: Assemble matrix
289: */
290: MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
291: MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
292: if (jac != B) {
293: MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);
294: MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);
295: }
296: return 0;
297: }
299: /*TEST
301: test:
302: args: -ksp_gmres_cgs_refinement_type refine_always -snes_monitor_short
303: requires: !single
305: test:
306: suffix: 2
307: requires: !single
308: args: -snes_monitor_short
309: output_file: output/ex1_1.out
311: test:
312: suffix: 3
313: args: -ksp_view_solution ascii:ex1_2_sol.tmp:ascii_matlab -snes_monitor_short
314: requires: !single
315: output_file: output/ex1_1.out
317: test:
318: suffix: 4
319: args: -ksp_view_solution ascii:ex1_2_sol.tmp::append -snes_monitor_short
320: requires: !single
321: output_file: output/ex1_1.out
323: test:
324: suffix: 5
325: args: -ksp_view_solution ascii:ex1_2_sol.tmp:ascii_matlab:append -snes_monitor_short
326: requires: !single
327: output_file: output/ex1_1.out
329: test:
330: suffix: 6
331: args: -ksp_view_solution ascii:ex1_2_sol.tmp:default:append -snes_monitor_short
332: requires: !single
333: output_file: output/ex1_1.out
335: test:
336: suffix: X
337: args: -ksp_monitor_short -ksp_type gmres -ksp_gmres_krylov_monitor -snes_monitor_short -snes_rtol 1.e-4
338: requires: !single x
340: TEST*/