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