xref: /petsc/src/snes/tutorials/ex59.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
1c4762a1bSJed Brown 
2c4762a1bSJed Brown static const char help[] = "Tries to solve u`` + u^{2} = f for an easy case and an impossible case.\n\n";
3c4762a1bSJed Brown 
4c4762a1bSJed Brown /*
5c4762a1bSJed Brown        This example was contributed by Peter Graf to show how SNES fails when given a nonlinear problem with no solution.
6c4762a1bSJed Brown 
7c4762a1bSJed Brown        Run with -n 14 to see fail to converge and -n 15 to see convergence
8c4762a1bSJed Brown 
9c4762a1bSJed Brown        The option -second_order uses a different discretization of the Neumann boundary condition and always converges
10c4762a1bSJed Brown 
11c4762a1bSJed Brown */
12c4762a1bSJed Brown 
13c4762a1bSJed Brown #include <petscsnes.h>
14c4762a1bSJed Brown 
15c4762a1bSJed Brown PetscBool second_order = PETSC_FALSE;
16c4762a1bSJed Brown #define X0DOT -2.0
17c4762a1bSJed Brown #define X1    5.0
18c4762a1bSJed Brown #define KPOW  2.0
19c4762a1bSJed Brown const PetscScalar sperturb = 1.1;
20c4762a1bSJed Brown 
21c4762a1bSJed Brown /*
22c4762a1bSJed Brown    User-defined routines
23c4762a1bSJed Brown */
24c4762a1bSJed Brown PetscErrorCode FormJacobian(SNES, Vec, Mat, Mat, void *);
25c4762a1bSJed Brown PetscErrorCode FormFunction(SNES, Vec, Vec, void *);
26c4762a1bSJed Brown 
27*9371c9d4SSatish Balay int main(int argc, char **argv) {
28c4762a1bSJed Brown   SNES              snes;    /* SNES context */
29c4762a1bSJed Brown   Vec               x, r, F; /* vectors */
30c4762a1bSJed Brown   Mat               J;       /* Jacobian */
31c4762a1bSJed Brown   PetscInt          it, n = 11, i;
32c4762a1bSJed Brown   PetscReal         h, xp = 0.0;
33c4762a1bSJed Brown   PetscScalar       v;
34c4762a1bSJed Brown   const PetscScalar a = X0DOT;
35c4762a1bSJed Brown   const PetscScalar b = X1;
36c4762a1bSJed Brown   const PetscScalar k = KPOW;
37c4762a1bSJed Brown   PetscScalar       v2;
38c4762a1bSJed Brown   PetscScalar      *xx;
39c4762a1bSJed Brown 
40327415f7SBarry Smith   PetscFunctionBeginUser;
419566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &argv, (char *)0, help));
429566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-n", &n, NULL));
439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-second_order", &second_order, NULL));
44c4762a1bSJed Brown   h = 1.0 / (n - 1);
45c4762a1bSJed Brown 
46c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
47c4762a1bSJed Brown      Create nonlinear solver context
48c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
49c4762a1bSJed Brown 
509566063dSJacob Faibussowitsch   PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes));
51c4762a1bSJed Brown 
52c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
53c4762a1bSJed Brown      Create vector data structures; set function evaluation routine
54c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
55c4762a1bSJed Brown 
569566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &x));
579566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(x, PETSC_DECIDE, n));
589566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(x));
599566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &r));
609566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &F));
61c4762a1bSJed Brown 
629566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, FormFunction, (void *)F));
63c4762a1bSJed Brown 
64c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
65c4762a1bSJed Brown      Create matrix data structures; set Jacobian evaluation routine
66c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
67c4762a1bSJed Brown 
689566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, n, n, 3, NULL, &J));
69c4762a1bSJed Brown 
70c4762a1bSJed Brown   /*
71c4762a1bSJed Brown      Note that in this case we create separate matrices for the Jacobian
72c4762a1bSJed Brown      and preconditioner matrix.  Both of these are computed in the
73c4762a1bSJed Brown      routine FormJacobian()
74c4762a1bSJed Brown   */
759566063dSJacob Faibussowitsch   /*  PetscCall(SNESSetJacobian(snes,NULL,JPrec,FormJacobian,0)); */
769566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, J, J, FormJacobian, 0));
779566063dSJacob Faibussowitsch   /*  PetscCall(SNESSetJacobian(snes,J,JPrec,FormJacobian,0)); */
78c4762a1bSJed Brown 
79c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
80c4762a1bSJed Brown      Customize nonlinear solver; set runtime options
81c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
82c4762a1bSJed Brown 
839566063dSJacob Faibussowitsch   PetscCall(SNESSetFromOptions(snes));
84c4762a1bSJed Brown 
85c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
86c4762a1bSJed Brown      Initialize application:
87c4762a1bSJed Brown      Store right-hand-side of PDE and exact solution
88c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
89c4762a1bSJed Brown 
90c4762a1bSJed Brown   /* set right hand side and initial guess to be exact solution of continuim problem */
91c4762a1bSJed Brown #define SQR(x) ((x) * (x))
92c4762a1bSJed Brown   xp = 0.0;
93*9371c9d4SSatish Balay   for (i = 0; i < n; i++) {
94c4762a1bSJed Brown     v = k * (k - 1.) * (b - a) * PetscPowScalar(xp, k - 2.) + SQR(a * xp) + SQR(b - a) * PetscPowScalar(xp, 2. * k) + 2. * a * (b - a) * PetscPowScalar(xp, k + 1.);
959566063dSJacob Faibussowitsch     PetscCall(VecSetValues(F, 1, &i, &v, INSERT_VALUES));
96c4762a1bSJed Brown     v2 = a * xp + (b - a) * PetscPowScalar(xp, k);
979566063dSJacob Faibussowitsch     PetscCall(VecSetValues(x, 1, &i, &v2, INSERT_VALUES));
98c4762a1bSJed Brown     xp += h;
99c4762a1bSJed Brown   }
100c4762a1bSJed Brown 
101c4762a1bSJed Brown   /* perturb initial guess */
1029566063dSJacob Faibussowitsch   PetscCall(VecGetArray(x, &xx));
103c4762a1bSJed Brown   for (i = 0; i < n; i++) {
104c4762a1bSJed Brown     v2 = xx[i] * sperturb;
1059566063dSJacob Faibussowitsch     PetscCall(VecSetValues(x, 1, &i, &v2, INSERT_VALUES));
106c4762a1bSJed Brown   }
1079566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(x, &xx));
108c4762a1bSJed Brown 
1099566063dSJacob Faibussowitsch   PetscCall(SNESSolve(snes, NULL, x));
1109566063dSJacob Faibussowitsch   PetscCall(SNESGetIterationNumber(snes, &it));
11163a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_SELF, "SNES iterations = %" PetscInt_FMT "\n\n", it));
112c4762a1bSJed Brown 
113c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
114c4762a1bSJed Brown      Free work space.  All PETSc objects should be destroyed when they
115c4762a1bSJed Brown      are no longer needed.
116c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
117c4762a1bSJed Brown 
118*9371c9d4SSatish Balay   PetscCall(VecDestroy(&x));
119*9371c9d4SSatish Balay   PetscCall(VecDestroy(&r));
120*9371c9d4SSatish Balay   PetscCall(VecDestroy(&F));
121*9371c9d4SSatish Balay   PetscCall(MatDestroy(&J));
1229566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes));
1239566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
124b122ec5aSJacob Faibussowitsch   return 0;
125c4762a1bSJed Brown }
126c4762a1bSJed Brown 
127*9371c9d4SSatish Balay PetscErrorCode FormFunction(SNES snes, Vec x, Vec f, void *dummy) {
128c4762a1bSJed Brown   const PetscScalar *xx;
129c4762a1bSJed Brown   PetscScalar       *ff, *FF, d, d2;
130c4762a1bSJed Brown   PetscInt           i, n;
131c4762a1bSJed Brown 
1329566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
1339566063dSJacob Faibussowitsch   PetscCall(VecGetArray(f, &ff));
1349566063dSJacob Faibussowitsch   PetscCall(VecGetArray((Vec)dummy, &FF));
1359566063dSJacob Faibussowitsch   PetscCall(VecGetSize(x, &n));
136*9371c9d4SSatish Balay   d  = (PetscReal)(n - 1);
137*9371c9d4SSatish Balay   d2 = d * d;
138c4762a1bSJed Brown 
139c4762a1bSJed Brown   if (second_order) ff[0] = d * (0.5 * d * (-xx[2] + 4. * xx[1] - 3. * xx[0]) - X0DOT);
140c4762a1bSJed Brown   else ff[0] = d * (d * (xx[1] - xx[0]) - X0DOT);
141c4762a1bSJed Brown 
142c4762a1bSJed Brown   for (i = 1; i < n - 1; i++) ff[i] = d2 * (xx[i - 1] - 2. * xx[i] + xx[i + 1]) + xx[i] * xx[i] - FF[i];
143c4762a1bSJed Brown 
144c4762a1bSJed Brown   ff[n - 1] = d * d * (xx[n - 1] - X1);
1459566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
1469566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(f, &ff));
1479566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray((Vec)dummy, &FF));
148c4762a1bSJed Brown   return 0;
149c4762a1bSJed Brown }
150c4762a1bSJed Brown 
151*9371c9d4SSatish Balay PetscErrorCode FormJacobian(SNES snes, Vec x, Mat jac, Mat prejac, void *dummy) {
152c4762a1bSJed Brown   const PetscScalar *xx;
153c4762a1bSJed Brown   PetscScalar        A[3], d, d2;
154c4762a1bSJed Brown   PetscInt           i, n, j[3];
155c4762a1bSJed Brown 
1569566063dSJacob Faibussowitsch   PetscCall(VecGetSize(x, &n));
1579566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
158*9371c9d4SSatish Balay   d  = (PetscReal)(n - 1);
159*9371c9d4SSatish Balay   d2 = d * d;
160c4762a1bSJed Brown 
161c4762a1bSJed Brown   i = 0;
162c4762a1bSJed Brown   if (second_order) {
163*9371c9d4SSatish Balay     j[0] = 0;
164*9371c9d4SSatish Balay     j[1] = 1;
165*9371c9d4SSatish Balay     j[2] = 2;
166*9371c9d4SSatish Balay     A[0] = -3. * d * d * 0.5;
167*9371c9d4SSatish Balay     A[1] = 4. * d * d * 0.5;
168*9371c9d4SSatish Balay     A[2] = -1. * d * d * 0.5;
1699566063dSJacob Faibussowitsch     PetscCall(MatSetValues(prejac, 1, &i, 3, j, A, INSERT_VALUES));
170c4762a1bSJed Brown   } else {
171*9371c9d4SSatish Balay     j[0] = 0;
172*9371c9d4SSatish Balay     j[1] = 1;
173*9371c9d4SSatish Balay     A[0] = -d * d;
174*9371c9d4SSatish Balay     A[1] = d * d;
1759566063dSJacob Faibussowitsch     PetscCall(MatSetValues(prejac, 1, &i, 2, j, A, INSERT_VALUES));
176c4762a1bSJed Brown   }
177c4762a1bSJed Brown   for (i = 1; i < n - 1; i++) {
178*9371c9d4SSatish Balay     j[0] = i - 1;
179*9371c9d4SSatish Balay     j[1] = i;
180*9371c9d4SSatish Balay     j[2] = i + 1;
181*9371c9d4SSatish Balay     A[0] = d2;
182*9371c9d4SSatish Balay     A[1] = -2. * d2 + 2. * xx[i];
183*9371c9d4SSatish Balay     A[2] = d2;
1849566063dSJacob Faibussowitsch     PetscCall(MatSetValues(prejac, 1, &i, 3, j, A, INSERT_VALUES));
185c4762a1bSJed Brown   }
186c4762a1bSJed Brown 
187c4762a1bSJed Brown   i    = n - 1;
188c4762a1bSJed Brown   A[0] = d * d;
1899566063dSJacob Faibussowitsch   PetscCall(MatSetValues(prejac, 1, &i, 1, &i, &A[0], INSERT_VALUES));
190c4762a1bSJed Brown 
1919566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(jac, MAT_FINAL_ASSEMBLY));
1929566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(jac, MAT_FINAL_ASSEMBLY));
1939566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(prejac, MAT_FINAL_ASSEMBLY));
1949566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(prejac, MAT_FINAL_ASSEMBLY));
195c4762a1bSJed Brown 
1969566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
197c4762a1bSJed Brown   return 0;
198c4762a1bSJed Brown }
199c4762a1bSJed Brown 
200c4762a1bSJed Brown /*TEST
201c4762a1bSJed Brown 
202c4762a1bSJed Brown    test:
203c4762a1bSJed Brown       args: -n 14 -snes_monitor_short -snes_converged_reason
204c4762a1bSJed Brown       requires: !single
205c4762a1bSJed Brown 
206c4762a1bSJed Brown    test:
207c4762a1bSJed Brown       suffix: 2
208c4762a1bSJed Brown       args: -n 15 -snes_monitor_short -snes_converged_reason
209c4762a1bSJed Brown       requires: !single
210c4762a1bSJed Brown 
211c4762a1bSJed Brown    test:
212c4762a1bSJed Brown       suffix: 3
213c4762a1bSJed Brown       args: -n 14 -second_order -snes_monitor_short -snes_converged_reason
214c4762a1bSJed Brown       requires: !single
215c4762a1bSJed Brown 
216c4762a1bSJed Brown TEST*/
217