Actual source code: ex44.c
petsc-3.3-p7 2013-05-11
2: static char help[] = "u`` + u^{2} = f. \n\
3: Demonstrates the use of matrix-free Newton-Krylov methods in conjunction\n\
4: with a user-provided preconditioner. Simplified from ex6.c\n\
5: Input arguments are:\n\
6: -snes_mf : Use matrix-free Newton methods\n\
7: -user_precond : Employ a user-defined preconditioner. Used only with\n\
8: matrix-free methods in this example.\n\n";
10: /*
11: Example:
12: ./ex44 -snes_mf -snes_monitor -snes_view
13: ./ex44 -snes_mf -user_precond -snes_monitor -snes_view
14: */
16: /*T
17: Concepts: SNES^different matrices for the Jacobian and preconditioner;
18: Concepts: SNES^matrix-free methods
19: Concepts: SNES^user-provided preconditioner;
20: Concepts: matrix-free methods
21: Concepts: user-provided preconditioner;
22: Processors: 1
23: T*/
25: #include <petscsnes.h>
27: /* User-defined routines */
28: PetscErrorCode FormFunction(SNES,Vec,Vec,void*);
29: PetscErrorCode MatrixFreePreconditioner(PC,Vec,Vec);
31: int main(int argc,char **argv)
32: {
33: SNES snes; /* SNES context */
34: KSP ksp; /* KSP context */
35: PC pc; /* PC context */
36: Vec x,r,F; /* vectors */
38: PetscInt it,n = 5,i;
39: PetscMPIInt size;
40: PetscReal h,xp = 0.0;
41: PetscScalar v,pfive = .5;
42: PetscBool flg;
44: PetscInitialize(&argc,&argv,(char *)0,help);
45: MPI_Comm_size(PETSC_COMM_WORLD,&size);
46: if (size != 1) SETERRQ(PETSC_COMM_SELF,1,"This is a uniprocessor example only!");
47: PetscOptionsGetInt(PETSC_NULL,"-n",&n,PETSC_NULL);
48: h = 1.0/(n-1);
50: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
51: Create nonlinear solver context
52: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
53: SNESCreate(PETSC_COMM_WORLD,&snes);
55: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
56: Create vector data structures; set function evaluation routine
57: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
58: VecCreate(PETSC_COMM_SELF,&x);
59: VecSetSizes(x,PETSC_DECIDE,n);
60: VecSetFromOptions(x);
61: VecDuplicate(x,&r);
62: VecDuplicate(x,&F);
64: SNESSetFunction(snes,r,FormFunction,(void*)F);
66: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
67: Customize nonlinear solver; set runtime options
68: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
69: /* Set preconditioner for matrix-free method */
70: flg = PETSC_FALSE;
71: PetscOptionsGetBool(PETSC_NULL,"-snes_mf",&flg,PETSC_NULL);
72: if (flg) {
73: SNESGetKSP(snes,&ksp);
74: KSPGetPC(ksp,&pc);
75: PetscOptionsHasName(PETSC_NULL,"-user_precond",&flg);
76: if (flg) { /* user-defined precond */
77: PCSetType(pc,PCSHELL);
78: PCShellSetApply(pc,MatrixFreePreconditioner);
79: } else {PCSetType(pc,PCNONE);}
80: }
82: SNESSetFromOptions(snes);
84: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
85: Initialize application:
86: Store right-hand-side of PDE and exact solution
87: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
88: //#if defined(TMP)
89: xp = 0.0;
90: for (i=0; i<n; i++) {
91: v = 6.0*xp + pow(xp+1.e-12,6.0); /* +1.e-12 is to prevent 0^6 */
92: VecSetValues(F,1,&i,&v,INSERT_VALUES);
93: xp += h;
94: }
95: //#endif
96: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
97: Evaluate initial guess; then solve nonlinear system
98: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
99: VecSet(x,pfive);
100: SNESSolve(snes,PETSC_NULL,x);
101: SNESGetIterationNumber(snes,&it);
102: PetscPrintf(PETSC_COMM_SELF,"SNES iterations = %D\n\n",it);
104: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
105: Free work space.
106: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
107: VecDestroy(&x);
108: VecDestroy(&r);
109: VecDestroy(&F);
110: SNESDestroy(&snes);
111: PetscFinalize();
112: return 0;
113: }
115: /* ------------------------------------------------------------------- */
116: /*
117: FormInitialGuess - Forms initial approximation.
119: Input Parameters:
120: user - user-defined application context
121: X - vector
123: Output Parameter:
124: X - vector
125: */
126: PetscErrorCode FormFunction(SNES snes,Vec x,Vec f,void *dummy)
127: {
128: PetscScalar *xx,*ff,*FF,d;
130: PetscInt i,n;
132: VecGetArray(x,&xx);
133: VecGetArray(f,&ff);
134: VecGetArray((Vec)dummy,&FF);
135: VecGetSize(x,&n);
136: d = (PetscReal)(n - 1); d = d*d;
137: ff[0] = xx[0];
138: for (i=1; i<n-1; i++) {
139: ff[i] = d*(xx[i-1] - 2.0*xx[i] + xx[i+1]) + xx[i]*xx[i] - FF[i];
140: }
141: ff[n-1] = xx[n-1] - 1.0;
142: VecRestoreArray(x,&xx);
143: VecRestoreArray(f,&ff);
144: VecRestoreArray((Vec)dummy,&FF);
145: return 0;
146: }
148: /* ------------------------------------------------------------------- */
149: /*
150: MatrixFreePreconditioner - This routine demonstrates the use of a
151: user-provided preconditioner. This code implements just the null
152: preconditioner, which of course is not recommended for general use.
154: Input Parameters:
155: + pc - preconditioner
156: - x - input vector
158: Output Parameter:
159: . y - preconditioned vector
160: */
161: PetscErrorCode MatrixFreePreconditioner(PC pc,Vec x,Vec y)
162: {
164: VecCopy(x,y);
165: return 0;
166: }