Date: 2013-07-02T14:49:51+00:00

Actual source code: ex2.c
petsc-3.4.2 2013-07-02

      2: static char help[] = "Newton method to solve u'' + u^{2} = f, sequentially.\n\
      3: This example employs a user-defined monitoring routine.\n\n";

      5: /*T
      6:    Concepts: SNES^basic uniprocessor example
      7:    Concepts: SNES^setting a user-defined monitoring routine
      8:    Processors: 1
      9: T*/

     11: /*
     12:    Include "petscdraw.h" so that we can use PETSc drawing routines.
     13:    Include "petscsnes.h" so that we can use SNES solvers.  Note that this
     14:    file automatically includes:
     15:      petscsys.h       - base PETSc routines   petscvec.h - vectors
     16:      petscmat.h - matrices
     17:      petscis.h     - index sets            petscksp.h - Krylov subspace methods
     18:      petscviewer.h - viewers               petscpc.h  - preconditioners
     19:      petscksp.h   - linear solvers
     20: */

     22: #include <petscsnes.h>

     24: /*
     25:    User-defined routines
     26: */
     27: extern PetscErrorCode FormJacobian(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
     28: extern PetscErrorCode FormFunction(SNES,Vec,Vec,void*);
     29: extern PetscErrorCode FormInitialGuess(Vec);
     30: extern PetscErrorCode Monitor(SNES,PetscInt,PetscReal,void*);

     32: /*
     33:    User-defined context for monitoring
     34: */
     35: typedef struct {
     36:   PetscViewer viewer;
     37: } MonitorCtx;

     41: int main(int argc,char **argv)
     42: {
     43:   SNES           snes;                   /* SNES context */
     44:   Vec            x,r,F,U;             /* vectors */
     45:   Mat            J;                      /* Jacobian matrix */
     46:   MonitorCtx     monP;                   /* monitoring context */
     48:   PetscInt       its,n = 5,i,maxit,maxf;
     49:   PetscMPIInt    size;
     50:   PetscScalar    h,xp,v,none = -1.0;
     51:   PetscReal      abstol,rtol,stol,norm;

     53:   PetscInitialize(&argc,&argv,(char*)0,help);
     54:   MPI_Comm_size(PETSC_COMM_WORLD,&size);
     55:   if (size != 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"This is a uniprocessor example only!");
     56:   PetscOptionsGetInt(NULL,"-n",&n,NULL);
     57:   h    = 1.0/(n-1);

     59:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     60:      Create nonlinear solver context
     61:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

     63:   SNESCreate(PETSC_COMM_WORLD,&snes);

     65:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     66:      Create vector data structures; set function evaluation routine
     67:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     68:   /*
     69:      Note that we form 1 vector from scratch and then duplicate as needed.
     70:   */
     71:   VecCreate(PETSC_COMM_WORLD,&x);
     72:   VecSetSizes(x,PETSC_DECIDE,n);
     73:   VecSetFromOptions(x);
     74:   VecDuplicate(x,&r);
     75:   VecDuplicate(x,&F);
     76:   VecDuplicate(x,&U);

     78:   /*
     79:      Set function evaluation routine and vector
     80:   */
     81:   SNESSetFunction(snes,r,FormFunction,(void*)F);

     84:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     85:      Create matrix data structure; set Jacobian evaluation routine
     86:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

     88:   MatCreate(PETSC_COMM_WORLD,&J);
     89:   MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,n,n);
     90:   MatSetFromOptions(J);
     91:   MatSeqAIJSetPreallocation(J,3,NULL);

     93:   /*
     94:      Set Jacobian matrix data structure and default Jacobian evaluation
     95:      routine. User can override with:
     96:      -snes_fd : default finite differencing approximation of Jacobian
     97:      -snes_mf : matrix-free Newton-Krylov method with no preconditioning
     98:                 (unless user explicitly sets preconditioner)
     99:      -snes_mf_operator : form preconditioning matrix as set by the user,
    100:                          but use matrix-free approx for Jacobian-vector
    101:                          products within Newton-Krylov method
    102:   */

    104:   SNESSetJacobian(snes,J,J,FormJacobian,NULL);

    106:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    107:      Customize nonlinear solver; set runtime options
    108:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    110:   /*
    111:      Set an optional user-defined monitoring routine
    112:   */
    113:   PetscViewerDrawOpen(PETSC_COMM_WORLD,0,0,0,0,400,400,&monP.viewer);
    114:   SNESMonitorSet(snes,Monitor,&monP,0);

    116:   /*
    117:      Set names for some vectors to facilitate monitoring (optional)
    118:   */
    119:   PetscObjectSetName((PetscObject)x,"Approximate Solution");
    120:   PetscObjectSetName((PetscObject)U,"Exact Solution");

    122:   /*
    123:      Set SNES/KSP/KSP/PC runtime options, e.g.,
    124:          -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc>
    125:   */
    126:   SNESSetFromOptions(snes);

    128:   /*
    129:      Print parameters used for convergence testing (optional) ... just
    130:      to demonstrate this routine; this information is also printed with
    131:      the option -snes_view
    132:   */
    133:   SNESGetTolerances(snes,&abstol,&rtol,&stol,&maxit,&maxf);
    134:   PetscPrintf(PETSC_COMM_WORLD,"atol=%G, rtol=%G, stol=%G, maxit=%D, maxf=%D\n",abstol,rtol,stol,maxit,maxf);

    136:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    137:      Initialize application:
    138:      Store right-hand-side of PDE and exact solution
    139:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    141:   xp = 0.0;
    142:   for (i=0; i<n; i++) {
    143:     v    = 6.0*xp + PetscPowScalar(xp+1.e-12,6.0); /* +1.e-12 is to prevent 0^6 */
    144:     VecSetValues(F,1,&i,&v,INSERT_VALUES);
    145:     v    = xp*xp*xp;
    146:     VecSetValues(U,1,&i,&v,INSERT_VALUES);
    147:     xp  += h;
    148:   }

    150:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    151:      Evaluate initial guess; then solve nonlinear system
    152:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    153:   /*
    154:      Note: The user should initialize the vector, x, with the initial guess
    155:      for the nonlinear solver prior to calling SNESSolve().  In particular,
    156:      to employ an initial guess of zero, the user should explicitly set
    157:      this vector to zero by calling VecSet().
    158:   */
    159:   FormInitialGuess(x);
    160:   SNESSolve(snes,NULL,x);
    161:   SNESGetIterationNumber(snes,&its);
    162:   PetscPrintf(PETSC_COMM_WORLD,"number of SNES iterations = %D\n\n",its);

    164:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    165:      Check solution and clean up
    166:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    168:   /*
    169:      Check the error
    170:   */
    171:   VecAXPY(x,none,U);
    172:   VecNorm(x,NORM_2,&norm);
    173:   PetscPrintf(PETSC_COMM_WORLD,"Norm of error %G, Iterations %D\n",norm,its);

    176:   /*
    177:      Free work space.  All PETSc objects should be destroyed when they
    178:      are no longer needed.
    179:   */
    180:   VecDestroy(&x);  VecDestroy(&r);
    181:   VecDestroy(&U);  VecDestroy(&F);
    182:   MatDestroy(&J);  SNESDestroy(&snes);
    183:   PetscViewerDestroy(&monP.viewer);
    184:   PetscFinalize();

    186:   return 0;
    187: }
    188: /* ------------------------------------------------------------------- */
    191: /*
    192:    FormInitialGuess - Computes initial guess.

    194:    Input/Output Parameter:
    195: .  x - the solution vector
    196: */
    197: PetscErrorCode FormInitialGuess(Vec x)
    198: {
    200:   PetscScalar    pfive = .50;
    201:   VecSet(x,pfive);
    202:   return 0;
    203: }
    204: /* ------------------------------------------------------------------- */
    207: /*
    208:    FormFunction - Evaluates nonlinear function, F(x).

    210:    Input Parameters:
    211: .  snes - the SNES context
    212: .  x - input vector
    213: .  ctx - optional user-defined context, as set by SNESSetFunction()

    215:    Output Parameter:
    216: .  f - function vector

    218:    Note:
    219:    The user-defined context can contain any application-specific data
    220:    needed for the function evaluation (such as various parameters, work
    221:    vectors, and grid information).  In this program the context is just
    222:    a vector containing the right-hand-side of the discretized PDE.
    223:  */

    225: PetscErrorCode FormFunction(SNES snes,Vec x,Vec f,void *ctx)
    226: {
    227:   Vec               g = (Vec)ctx;
    228:   const PetscScalar *xx,*gg;
    229:   PetscScalar       *ff,d;
    230:   PetscErrorCode    ierr;
    231:   PetscInt          i,n;

    233:   /*
    234:      Get pointers to vector data.
    235:        - For default PETSc vectors, VecGetArray() returns a pointer to
    236:          the data array.  Otherwise, the routine is implementation dependent.
    237:        - You MUST call VecRestoreArray() when you no longer need access to
    238:          the array.
    239:   */
    240:   VecGetArrayRead(x,&xx);
    241:   VecGetArray(f,&ff);
    242:   VecGetArrayRead(g,&gg);

    244:   /*
    245:      Compute function
    246:   */
    247:   VecGetSize(x,&n);
    248:   d     = (PetscReal)(n - 1); d = d*d;
    249:   ff[0] = xx[0];
    250:   for (i=1; i<n-1; i++) ff[i] = d*(xx[i-1] - 2.0*xx[i] + xx[i+1]) + xx[i]*xx[i] - gg[i];
    251:   ff[n-1] = xx[n-1] - 1.0;

    253:   /*
    254:      Restore vectors
    255:   */
    256:   VecRestoreArrayRead(x,&xx);
    257:   VecRestoreArray(f,&ff);
    258:   VecRestoreArrayRead(g,&gg);
    259:   return 0;
    260: }
    261: /* ------------------------------------------------------------------- */
    264: /*
    265:    FormJacobian - Evaluates Jacobian matrix.

    267:    Input Parameters:
    268: .  snes - the SNES context
    269: .  x - input vector
    270: .  dummy - optional user-defined context (not used here)

    272:    Output Parameters:
    273: .  jac - Jacobian matrix
    274: .  B - optionally different preconditioning matrix
    275: .  flag - flag indicating matrix structure
    276: */

    278: PetscErrorCode FormJacobian(SNES snes,Vec x,Mat *jac,Mat *B,MatStructure *flag,void *dummy)
    279: {
    280:   const PetscScalar *xx;
    281:   PetscScalar       A[3],d;
    282:   PetscErrorCode    ierr;
    283:   PetscInt          i,n,j[3];

    285:   /*
    286:      Get pointer to vector data
    287:   */
    288:   VecGetArrayRead(x,&xx);

    290:   /*
    291:      Compute Jacobian entries and insert into matrix.
    292:       - Note that in this case we set all elements for a particular
    293:         row at once.
    294:   */
    295:   VecGetSize(x,&n);
    296:   d    = (PetscReal)(n - 1); d = d*d;

    298:   /*
    299:      Interior grid points
    300:   */
    301:   for (i=1; i<n-1; i++) {
    302:     j[0] = i - 1; j[1] = i; j[2] = i + 1;
    303:     A[0] = A[2] = d; A[1] = -2.0*d + 2.0*xx[i];
    304:     MatSetValues(*jac,1,&i,3,j,A,INSERT_VALUES);
    305:   }

    307:   /*
    308:      Boundary points
    309:   */
    310:   i = 0;   A[0] = 1.0;

    312:   MatSetValues(*jac,1,&i,1,&i,A,INSERT_VALUES);

    314:   i = n-1; A[0] = 1.0;

    316:   MatSetValues(*jac,1,&i,1,&i,A,INSERT_VALUES);

    318:   /*
    319:      Restore vector
    320:   */
    321:   VecRestoreArrayRead(x,&xx);

    323:   /*
    324:      Assemble matrix
    325:   */
    326:   MatAssemblyBegin(*jac,MAT_FINAL_ASSEMBLY);
    327:   MatAssemblyEnd(*jac,MAT_FINAL_ASSEMBLY);
    328:   if (*jac != *B) {
    329:     MatAssemblyBegin(*jac,MAT_FINAL_ASSEMBLY);
    330:     MatAssemblyEnd(*jac,MAT_FINAL_ASSEMBLY);
    331:   }
    332:   return 0;
    333: }
    334: /* ------------------------------------------------------------------- */
    337: /*
    338:    Monitor - User-defined monitoring routine that views the
    339:    current iterate with an x-window plot.

    341:    Input Parameters:
    342:    snes - the SNES context
    343:    its - iteration number
    344:    norm - 2-norm function value (may be estimated)
    345:    ctx - optional user-defined context for private data for the
    346:          monitor routine, as set by SNESMonitorSet()

    348:    Note:
    349:    See the manpage for PetscViewerDrawOpen() for useful runtime options,
    350:    such as -nox to deactivate all x-window output.
    351:  */
    352: PetscErrorCode Monitor(SNES snes,PetscInt its,PetscReal fnorm,void *ctx)
    353: {
    355:   MonitorCtx     *monP = (MonitorCtx*) ctx;
    356:   Vec            x;

    358:   PetscPrintf(PETSC_COMM_WORLD,"iter = %D, SNES Function norm %G\n",its,fnorm);
    359:   SNESGetSolution(snes,&x);
    360:   VecView(x,monP->viewer);
    361:   return 0;
    362: }