Actual source code: ex1.c


  2: static char help[] = "Newton's method for a two-variable system, sequential.\n\n";

  4: /*T
  5:    Concepts: SNES^basic example
  6: T*/

  8: /*
  9:    Include "petscsnes.h" so that we can use SNES solvers.  Note that this
 10:    file automatically includes:
 11:      petscsys.h       - base PETSc routines   petscvec.h - vectors
 12:      petscmat.h - matrices
 13:      petscis.h     - index sets            petscksp.h - Krylov subspace methods
 14:      petscviewer.h - viewers               petscpc.h  - preconditioners
 15:      petscksp.h   - linear solvers
 16: */
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}
 27: #include <petscsnes.h>

 29: /*
 30:    User-defined routines
 31: */
 32: extern PetscErrorCode FormJacobian1(SNES,Vec,Mat,Mat,void*);
 33: extern PetscErrorCode FormFunction1(SNES,Vec,Vec,void*);
 34: extern PetscErrorCode FormJacobian2(SNES,Vec,Mat,Mat,void*);
 35: extern PetscErrorCode FormFunction2(SNES,Vec,Vec,void*);

 37: int main(int argc,char **argv)
 38: {
 39:   SNES           snes;         /* nonlinear solver context */
 40:   KSP            ksp;          /* linear solver context */
 41:   PC             pc;           /* preconditioner context */
 42:   Vec            x,r;          /* solution, residual vectors */
 43:   Mat            J;            /* Jacobian matrix */
 45:   PetscMPIInt    size;
 46:   PetscScalar    pfive = .5,*xx;
 47:   PetscBool      flg;

 49:   PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr;
 50:   MPI_Comm_size(PETSC_COMM_WORLD,&size);
 51:   if (size > 1) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"Example is only for sequential runs");

 53:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 54:      Create nonlinear solver context
 55:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 56:   SNESCreate(PETSC_COMM_WORLD,&snes);

 58:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 59:      Create matrix and vector data structures; set corresponding routines
 60:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 61:   /*
 62:      Create vectors for solution and nonlinear function
 63:   */
 64:   VecCreate(PETSC_COMM_WORLD,&x);
 65:   VecSetSizes(x,PETSC_DECIDE,2);
 66:   VecSetFromOptions(x);
 67:   VecDuplicate(x,&r);

 69:   /*
 70:      Create Jacobian matrix data structure
 71:   */
 72:   MatCreate(PETSC_COMM_WORLD,&J);
 73:   MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,2,2);
 74:   MatSetFromOptions(J);
 75:   MatSetUp(J);

 77:   PetscOptionsHasName(NULL,NULL,"-hard",&flg);
 78:   if (!flg) {
 79:     /*
 80:      Set function evaluation routine and vector.
 81:     */
 82:     SNESSetFunction(snes,r,FormFunction1,NULL);

 84:     /*
 85:      Set Jacobian matrix data structure and Jacobian evaluation routine
 86:     */
 87:     SNESSetJacobian(snes,J,J,FormJacobian1,NULL);
 88:   } else {
 89:     SNESSetFunction(snes,r,FormFunction2,NULL);
 90:     SNESSetJacobian(snes,J,J,FormJacobian2,NULL);
 91:   }

 93:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 94:      Customize nonlinear solver; set runtime options
 95:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 96:   /*
 97:      Set linear solver defaults for this problem. By extracting the
 98:      KSP and PC contexts from the SNES context, we can then
 99:      directly call any KSP and PC routines to set various options.
100:   */
101:   SNESGetKSP(snes,&ksp);
102:   KSPGetPC(ksp,&pc);
103:   PCSetType(pc,PCNONE);
104:   KSPSetTolerances(ksp,1.e-4,PETSC_DEFAULT,PETSC_DEFAULT,20);

106:   /*
107:      Set SNES/KSP/KSP/PC runtime options, e.g.,
108:          -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc>
109:      These options will override those specified above as long as
110:      SNESSetFromOptions() is called _after_ any other customization
111:      routines.
112:   */
113:   SNESSetFromOptions(snes);

115:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
116:      Evaluate initial guess; then solve nonlinear system
117:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
118:   if (!flg) {
119:     VecSet(x,pfive);
120:   } else {
121:     VecGetArray(x,&xx);
122:     xx[0] = 2.0; xx[1] = 3.0;
123:     VecRestoreArray(x,&xx);
124:   }
125:   /*
126:      Note: The user should initialize the vector, x, with the initial guess
127:      for the nonlinear solver prior to calling SNESSolve().  In particular,
128:      to employ an initial guess of zero, the user should explicitly set
129:      this vector to zero by calling VecSet().
130:   */

132:   SNESSolve(snes,NULL,x);
133:   if (flg) {
134:     Vec f;
135:     VecView(x,PETSC_VIEWER_STDOUT_WORLD);
136:     SNESGetFunction(snes,&f,0,0);
137:     VecView(r,PETSC_VIEWER_STDOUT_WORLD);
138:   }

140:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
141:      Free work space.  All PETSc objects should be destroyed when they
142:      are no longer needed.
143:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

145:   VecDestroy(&x); VecDestroy(&r);
146:   MatDestroy(&J); SNESDestroy(&snes);
147:   PetscFinalize();
148:   return ierr;
149: }
150: /* ------------------------------------------------------------------- */
151: /*
152:    FormFunction1 - Evaluates nonlinear function, F(x).

154:    Input Parameters:
155: .  snes - the SNES context
156: .  x    - input vector
157: .  ctx  - optional user-defined context

159:    Output Parameter:
160: .  f - function vector
161:  */
162: PetscErrorCode FormFunction1(SNES snes,Vec x,Vec f,void *ctx)
163: {
164:   PetscErrorCode    ierr;
165:   const PetscScalar *xx;
166:   PetscScalar       *ff;

168:   /*
169:    Get pointers to vector data.
170:       - For default PETSc vectors, VecGetArray() returns a pointer to
171:         the data array.  Otherwise, the routine is implementation dependent.
172:       - You MUST call VecRestoreArray() when you no longer need access to
173:         the array.
174:    */
175:   VecGetArrayRead(x,&xx);
176:   VecGetArray(f,&ff);

178:   /* Compute function */
179:   ff[0] = xx[0]*xx[0] + xx[0]*xx[1] - 3.0;
180:   ff[1] = xx[0]*xx[1] + xx[1]*xx[1] - 6.0;

182:   /* Restore vectors */
183:   VecRestoreArrayRead(x,&xx);
184:   VecRestoreArray(f,&ff);
185:   return 0;
186: }
187: /* ------------------------------------------------------------------- */
188: /*
189:    FormJacobian1 - Evaluates Jacobian matrix.

191:    Input Parameters:
192: .  snes - the SNES context
193: .  x - input vector
194: .  dummy - optional user-defined context (not used here)

196:    Output Parameters:
197: .  jac - Jacobian matrix
198: .  B - optionally different preconditioning matrix
199: .  flag - flag indicating matrix structure
200: */
201: PetscErrorCode FormJacobian1(SNES snes,Vec x,Mat jac,Mat B,void *dummy)
202: {
203:   const PetscScalar *xx;
204:   PetscScalar       A[4];
205:   PetscErrorCode    ierr;
206:   PetscInt          idx[2] = {0,1};

208:   /*
209:      Get pointer to vector data
210:   */
211:   VecGetArrayRead(x,&xx);

213:   /*
214:      Compute Jacobian entries and insert into matrix.
215:       - Since this is such a small problem, we set all entries for
216:         the matrix at once.
217:   */
218:   A[0]  = 2.0*xx[0] + xx[1]; A[1] = xx[0];
219:   A[2]  = xx[1]; A[3] = xx[0] + 2.0*xx[1];
220:   MatSetValues(B,2,idx,2,idx,A,INSERT_VALUES);

222:   /*
223:      Restore vector
224:   */
225:   VecRestoreArrayRead(x,&xx);

227:   /*
228:      Assemble matrix
229:   */
230:   MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
231:   MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
232:   if (jac != B) {
233:     MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);
234:     MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);
235:   }
236:   return 0;
237: }

239: /* ------------------------------------------------------------------- */
240: PetscErrorCode FormFunction2(SNES snes,Vec x,Vec f,void *dummy)
241: {
242:   PetscErrorCode    ierr;
243:   const PetscScalar *xx;
244:   PetscScalar       *ff;

246:   /*
247:      Get pointers to vector data.
248:        - For default PETSc vectors, VecGetArray() returns a pointer to
249:          the data array.  Otherwise, the routine is implementation dependent.
250:        - You MUST call VecRestoreArray() when you no longer need access to
251:          the array.
252:   */
253:   VecGetArrayRead(x,&xx);
254:   VecGetArray(f,&ff);

256:   /*
257:      Compute function
258:   */
259:   ff[0] = PetscSinScalar(3.0*xx[0]) + xx[0];
260:   ff[1] = xx[1];

262:   /*
263:      Restore vectors
264:   */
265:   VecRestoreArrayRead(x,&xx);
266:   VecRestoreArray(f,&ff);
267:   return 0;
268: }
269: /* ------------------------------------------------------------------- */
270: PetscErrorCode FormJacobian2(SNES snes,Vec x,Mat jac,Mat B,void *dummy)
271: {
272:   const PetscScalar *xx;
273:   PetscScalar       A[4];
274:   PetscErrorCode    ierr;
275:   PetscInt          idx[2] = {0,1};

277:   /*
278:      Get pointer to vector data
279:   */
280:   VecGetArrayRead(x,&xx);

282:   /*
283:      Compute Jacobian entries and insert into matrix.
284:       - Since this is such a small problem, we set all entries for
285:         the matrix at once.
286:   */
287:   A[0]  = 3.0*PetscCosScalar(3.0*xx[0]) + 1.0; A[1] = 0.0;
288:   A[2]  = 0.0;                     A[3] = 1.0;
289:   MatSetValues(B,2,idx,2,idx,A,INSERT_VALUES);

291:   /*
292:      Restore vector
293:   */
294:   VecRestoreArrayRead(x,&xx);

296:   /*
297:      Assemble matrix
298:   */
299:   MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
300:   MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
301:   if (jac != B) {
302:     MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);
303:     MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);
304:   }
305:   return 0;
306: }

308: /*TEST

310:    test:
311:       args: -ksp_gmres_cgs_refinement_type refine_always -snes_monitor_short
312:       requires: !single

314:    test:
315:       suffix: 2
316:       requires: !single
317:       args:  -snes_monitor_short
318:       output_file: output/ex1_1.out

320:    test:
321:       suffix: 3
322:       args: -ksp_view_solution ascii:ex1_2_sol.tmp:ascii_matlab  -snes_monitor_short
323:       requires: !single
324:       output_file: output/ex1_1.out

326:    test:
327:       suffix: 4
328:       args: -ksp_view_solution ascii:ex1_2_sol.tmp::append  -snes_monitor_short
329:       requires: !single
330:       output_file: output/ex1_1.out

332:    test:
333:       suffix: 5
334:       args: -ksp_view_solution ascii:ex1_2_sol.tmp:ascii_matlab:append  -snes_monitor_short
335:       requires: !single
336:       output_file: output/ex1_1.out

338:    test:
339:       suffix: 6
340:       args: -ksp_view_solution ascii:ex1_2_sol.tmp:default:append  -snes_monitor_short
341:       requires: !single
342:       output_file: output/ex1_1.out

344:    test:
345:       suffix: X
346:       args: -ksp_monitor_short -ksp_type gmres -ksp_gmres_krylov_monitor -snes_monitor_short -snes_rtol 1.e-4
347:       requires: !single x

349: TEST*/