xref: /petsc/src/snes/tutorials/ex59.c (revision c4762a1b19cd2af06abeed90e8f9d34fb975dd94)
1*c4762a1bSJed Brown 
2*c4762a1bSJed Brown static const char help[] = "Tries to solve u`` + u^{2} = f for an easy case and an impossible case.\n\n";
3*c4762a1bSJed Brown 
4*c4762a1bSJed Brown /*
5*c4762a1bSJed Brown        This example was contributed by Peter Graf to show how SNES fails when given a nonlinear problem with no solution.
6*c4762a1bSJed Brown 
7*c4762a1bSJed Brown        Run with -n 14 to see fail to converge and -n 15 to see convergence
8*c4762a1bSJed Brown 
9*c4762a1bSJed Brown        The option -second_order uses a different discretization of the Neumann boundary condition and always converges
10*c4762a1bSJed Brown 
11*c4762a1bSJed Brown */
12*c4762a1bSJed Brown 
13*c4762a1bSJed Brown #include <petscsnes.h>
14*c4762a1bSJed Brown 
15*c4762a1bSJed Brown PetscBool second_order = PETSC_FALSE;
16*c4762a1bSJed Brown #define X0DOT      -2.0
17*c4762a1bSJed Brown #define X1          5.0
18*c4762a1bSJed Brown #define KPOW        2.0
19*c4762a1bSJed Brown const PetscScalar sperturb = 1.1;
20*c4762a1bSJed Brown 
21*c4762a1bSJed Brown /*
22*c4762a1bSJed Brown    User-defined routines
23*c4762a1bSJed Brown */
24*c4762a1bSJed Brown PetscErrorCode FormJacobian(SNES,Vec,Mat,Mat,void*);
25*c4762a1bSJed Brown PetscErrorCode FormFunction(SNES,Vec,Vec,void*);
26*c4762a1bSJed Brown 
27*c4762a1bSJed Brown int main(int argc,char **argv)
28*c4762a1bSJed Brown {
29*c4762a1bSJed Brown   SNES              snes;                /* SNES context */
30*c4762a1bSJed Brown   Vec               x,r,F;               /* vectors */
31*c4762a1bSJed Brown   Mat               J;                   /* Jacobian */
32*c4762a1bSJed Brown   PetscErrorCode    ierr;
33*c4762a1bSJed Brown   PetscInt          it,n = 11,i;
34*c4762a1bSJed Brown   PetscReal         h,xp = 0.0;
35*c4762a1bSJed Brown   PetscScalar       v;
36*c4762a1bSJed Brown   const PetscScalar a = X0DOT;
37*c4762a1bSJed Brown   const PetscScalar b = X1;
38*c4762a1bSJed Brown   const PetscScalar k = KPOW;
39*c4762a1bSJed Brown   PetscScalar       v2;
40*c4762a1bSJed Brown   PetscScalar       *xx;
41*c4762a1bSJed Brown 
42*c4762a1bSJed Brown 
43*c4762a1bSJed Brown   ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr;
44*c4762a1bSJed Brown   ierr = PetscOptionsGetInt(NULL,NULL,"-n",&n,NULL);CHKERRQ(ierr);
45*c4762a1bSJed Brown   ierr = PetscOptionsGetBool(NULL,NULL,"-second_order",&second_order,NULL);CHKERRQ(ierr);
46*c4762a1bSJed Brown   h    = 1.0/(n-1);
47*c4762a1bSJed Brown 
48*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
49*c4762a1bSJed Brown      Create nonlinear solver context
50*c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
51*c4762a1bSJed Brown 
52*c4762a1bSJed Brown   ierr = SNESCreate(PETSC_COMM_WORLD,&snes);CHKERRQ(ierr);
53*c4762a1bSJed Brown 
54*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
55*c4762a1bSJed Brown      Create vector data structures; set function evaluation routine
56*c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
57*c4762a1bSJed Brown 
58*c4762a1bSJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&x);CHKERRQ(ierr);
59*c4762a1bSJed Brown   ierr = VecSetSizes(x,PETSC_DECIDE,n);CHKERRQ(ierr);
60*c4762a1bSJed Brown   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
61*c4762a1bSJed Brown   ierr = VecDuplicate(x,&r);CHKERRQ(ierr);
62*c4762a1bSJed Brown   ierr = VecDuplicate(x,&F);CHKERRQ(ierr);
63*c4762a1bSJed Brown 
64*c4762a1bSJed Brown   ierr = SNESSetFunction(snes,r,FormFunction,(void*)F);CHKERRQ(ierr);
65*c4762a1bSJed Brown 
66*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
67*c4762a1bSJed Brown      Create matrix data structures; set Jacobian evaluation routine
68*c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
69*c4762a1bSJed Brown 
70*c4762a1bSJed Brown   ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,n,n,3,NULL,&J);CHKERRQ(ierr);
71*c4762a1bSJed Brown 
72*c4762a1bSJed Brown   /*
73*c4762a1bSJed Brown      Note that in this case we create separate matrices for the Jacobian
74*c4762a1bSJed Brown      and preconditioner matrix.  Both of these are computed in the
75*c4762a1bSJed Brown      routine FormJacobian()
76*c4762a1bSJed Brown   */
77*c4762a1bSJed Brown   /*  ierr = SNESSetJacobian(snes,NULL,JPrec,FormJacobian,0);CHKERRQ(ierr); */
78*c4762a1bSJed Brown   ierr = SNESSetJacobian(snes,J,J,FormJacobian,0);CHKERRQ(ierr);
79*c4762a1bSJed Brown   /*  ierr = SNESSetJacobian(snes,J,JPrec,FormJacobian,0);CHKERRQ(ierr); */
80*c4762a1bSJed Brown 
81*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
82*c4762a1bSJed Brown      Customize nonlinear solver; set runtime options
83*c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
84*c4762a1bSJed Brown 
85*c4762a1bSJed Brown   ierr = SNESSetFromOptions(snes);CHKERRQ(ierr);
86*c4762a1bSJed Brown 
87*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
88*c4762a1bSJed Brown      Initialize application:
89*c4762a1bSJed Brown      Store right-hand-side of PDE and exact solution
90*c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
91*c4762a1bSJed Brown 
92*c4762a1bSJed Brown   /* set right hand side and initial guess to be exact solution of continuim problem */
93*c4762a1bSJed Brown #define SQR(x) ((x)*(x))
94*c4762a1bSJed Brown   xp = 0.0;
95*c4762a1bSJed Brown   for (i=0; i<n; i++)
96*c4762a1bSJed Brown   {
97*c4762a1bSJed 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.);
98*c4762a1bSJed Brown     ierr = VecSetValues(F,1,&i,&v,INSERT_VALUES);CHKERRQ(ierr);
99*c4762a1bSJed Brown     v2   = a*xp + (b-a)*PetscPowScalar(xp,k);
100*c4762a1bSJed Brown     ierr = VecSetValues(x,1,&i,&v2,INSERT_VALUES);CHKERRQ(ierr);
101*c4762a1bSJed Brown     xp  += h;
102*c4762a1bSJed Brown   }
103*c4762a1bSJed Brown 
104*c4762a1bSJed Brown   /* perturb initial guess */
105*c4762a1bSJed Brown   ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
106*c4762a1bSJed Brown   for (i=0; i<n; i++) {
107*c4762a1bSJed Brown     v2   = xx[i]*sperturb;
108*c4762a1bSJed Brown     ierr = VecSetValues(x,1,&i,&v2,INSERT_VALUES);CHKERRQ(ierr);
109*c4762a1bSJed Brown   }
110*c4762a1bSJed Brown   ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
111*c4762a1bSJed Brown 
112*c4762a1bSJed Brown 
113*c4762a1bSJed Brown   ierr = SNESSolve(snes,NULL,x);CHKERRQ(ierr);
114*c4762a1bSJed Brown   ierr = SNESGetIterationNumber(snes,&it);CHKERRQ(ierr);
115*c4762a1bSJed Brown   ierr = PetscPrintf(PETSC_COMM_SELF,"SNES iterations = %D\n\n",it);CHKERRQ(ierr);
116*c4762a1bSJed Brown 
117*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
118*c4762a1bSJed Brown      Free work space.  All PETSc objects should be destroyed when they
119*c4762a1bSJed Brown      are no longer needed.
120*c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
121*c4762a1bSJed Brown 
122*c4762a1bSJed Brown   ierr = VecDestroy(&x);CHKERRQ(ierr);     ierr = VecDestroy(&r);CHKERRQ(ierr);
123*c4762a1bSJed Brown   ierr = VecDestroy(&F);CHKERRQ(ierr);     ierr = MatDestroy(&J);CHKERRQ(ierr);
124*c4762a1bSJed Brown   ierr = SNESDestroy(&snes);CHKERRQ(ierr);
125*c4762a1bSJed Brown   ierr = PetscFinalize();
126*c4762a1bSJed Brown   return ierr;
127*c4762a1bSJed Brown }
128*c4762a1bSJed Brown 
129*c4762a1bSJed Brown PetscErrorCode FormFunction(SNES snes,Vec x,Vec f,void *dummy)
130*c4762a1bSJed Brown {
131*c4762a1bSJed Brown   const PetscScalar *xx;
132*c4762a1bSJed Brown   PetscScalar       *ff,*FF,d,d2;
133*c4762a1bSJed Brown   PetscErrorCode    ierr;
134*c4762a1bSJed Brown   PetscInt          i,n;
135*c4762a1bSJed Brown 
136*c4762a1bSJed Brown   ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
137*c4762a1bSJed Brown   ierr = VecGetArray(f,&ff);CHKERRQ(ierr);
138*c4762a1bSJed Brown   ierr = VecGetArray((Vec)dummy,&FF);CHKERRQ(ierr);
139*c4762a1bSJed Brown   ierr = VecGetSize(x,&n);CHKERRQ(ierr);
140*c4762a1bSJed Brown   d    = (PetscReal)(n - 1); d2 = d*d;
141*c4762a1bSJed Brown 
142*c4762a1bSJed Brown   if (second_order) ff[0] = d*(0.5*d*(-xx[2] + 4.*xx[1] - 3.*xx[0]) - X0DOT);
143*c4762a1bSJed Brown   else ff[0] = d*(d*(xx[1] - xx[0]) - X0DOT);
144*c4762a1bSJed Brown 
145*c4762a1bSJed 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];
146*c4762a1bSJed Brown 
147*c4762a1bSJed Brown   ff[n-1] = d*d*(xx[n-1] - X1);
148*c4762a1bSJed Brown   ierr    = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
149*c4762a1bSJed Brown   ierr    = VecRestoreArray(f,&ff);CHKERRQ(ierr);
150*c4762a1bSJed Brown   ierr    = VecRestoreArray((Vec)dummy,&FF);CHKERRQ(ierr);
151*c4762a1bSJed Brown   return 0;
152*c4762a1bSJed Brown }
153*c4762a1bSJed Brown 
154*c4762a1bSJed Brown PetscErrorCode FormJacobian(SNES snes,Vec x,Mat jac,Mat prejac,void *dummy)
155*c4762a1bSJed Brown {
156*c4762a1bSJed Brown   const PetscScalar *xx;
157*c4762a1bSJed Brown   PetscScalar       A[3],d,d2;
158*c4762a1bSJed Brown   PetscInt          i,n,j[3];
159*c4762a1bSJed Brown   PetscErrorCode    ierr;
160*c4762a1bSJed Brown 
161*c4762a1bSJed Brown   ierr = VecGetSize(x,&n);CHKERRQ(ierr);
162*c4762a1bSJed Brown   ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
163*c4762a1bSJed Brown   d    = (PetscReal)(n - 1); d2 = d*d;
164*c4762a1bSJed Brown 
165*c4762a1bSJed Brown   i = 0;
166*c4762a1bSJed Brown   if (second_order) {
167*c4762a1bSJed Brown     j[0] = 0; j[1] = 1; j[2] = 2;
168*c4762a1bSJed Brown     A[0] = -3.*d*d*0.5; A[1] = 4.*d*d*0.5;  A[2] = -1.*d*d*0.5;
169*c4762a1bSJed Brown     ierr = MatSetValues(prejac,1,&i,3,j,A,INSERT_VALUES);CHKERRQ(ierr);
170*c4762a1bSJed Brown   } else {
171*c4762a1bSJed Brown     j[0] = 0; j[1] = 1;
172*c4762a1bSJed Brown     A[0] = -d*d; A[1] = d*d;
173*c4762a1bSJed Brown     ierr = MatSetValues(prejac,1,&i,2,j,A,INSERT_VALUES);CHKERRQ(ierr);
174*c4762a1bSJed Brown   }
175*c4762a1bSJed Brown   for (i=1; i<n-1; i++) {
176*c4762a1bSJed Brown     j[0] = i - 1; j[1] = i;                   j[2] = i + 1;
177*c4762a1bSJed Brown     A[0] = d2;    A[1] = -2.*d2 + 2.*xx[i];  A[2] = d2;
178*c4762a1bSJed Brown     ierr = MatSetValues(prejac,1,&i,3,j,A,INSERT_VALUES);CHKERRQ(ierr);
179*c4762a1bSJed Brown   }
180*c4762a1bSJed Brown 
181*c4762a1bSJed Brown   i    = n-1;
182*c4762a1bSJed Brown   A[0] = d*d;
183*c4762a1bSJed Brown   ierr = MatSetValues(prejac,1,&i,1,&i,&A[0],INSERT_VALUES);CHKERRQ(ierr);
184*c4762a1bSJed Brown 
185*c4762a1bSJed Brown   ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
186*c4762a1bSJed Brown   ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
187*c4762a1bSJed Brown   ierr = MatAssemblyBegin(prejac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
188*c4762a1bSJed Brown   ierr = MatAssemblyEnd(prejac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
189*c4762a1bSJed Brown 
190*c4762a1bSJed Brown   ierr  = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
191*c4762a1bSJed Brown   return 0;
192*c4762a1bSJed Brown }
193*c4762a1bSJed Brown 
194*c4762a1bSJed Brown 
195*c4762a1bSJed Brown /*TEST
196*c4762a1bSJed Brown 
197*c4762a1bSJed Brown    test:
198*c4762a1bSJed Brown       args: -n 14 -snes_monitor_short -snes_converged_reason
199*c4762a1bSJed Brown       requires: !single
200*c4762a1bSJed Brown 
201*c4762a1bSJed Brown    test:
202*c4762a1bSJed Brown       suffix: 2
203*c4762a1bSJed Brown       args: -n 15 -snes_monitor_short -snes_converged_reason
204*c4762a1bSJed Brown       requires: !single
205*c4762a1bSJed Brown 
206*c4762a1bSJed Brown    test:
207*c4762a1bSJed Brown       suffix: 3
208*c4762a1bSJed Brown       args: -n 14 -second_order -snes_monitor_short -snes_converged_reason
209*c4762a1bSJed Brown       requires: !single
210*c4762a1bSJed Brown 
211*c4762a1bSJed Brown TEST*/
212