Actual source code: snesj.c

 2:  #include src/snes/snesimpl.h

  6: /*@C
  7:    SNESDefaultComputeJacobian - Computes the Jacobian using finite differences. 

  9:    Collective on SNES

 11:    Input Parameters:
 12: +  x1 - compute Jacobian at this point
 13: -  ctx - application's function context, as set with SNESSetFunction()

 15:    Output Parameters:
 16: +  J - Jacobian matrix (not altered in this routine)
 17: .  B - newly computed Jacobian matrix to use with preconditioner (generally the same as J)
 18: -  flag - flag indicating whether the matrix sparsity structure has changed

 20:    Options Database Key:
 21: +  -snes_fd - Activates SNESDefaultComputeJacobian()
 22: -  -snes_test_err - Square root of function error tolerance, default square root of machine
 23:                     epsilon (1.e-8 in double, 3.e-4 in single)

 25:    Notes:
 26:    This routine is slow and expensive, and is not currently optimized
 27:    to take advantage of sparsity in the problem.  Although
 28:    SNESDefaultComputeJacobian() is not recommended for general use
 29:    in large-scale applications, It can be useful in checking the
 30:    correctness of a user-provided Jacobian.

 32:    An alternative routine that uses coloring to explot matrix sparsity is
 33:    SNESDefaultComputeJacobianColor().

 35:    Level: intermediate

 37: .keywords: SNES, finite differences, Jacobian

 39: .seealso: SNESSetJacobian(), SNESDefaultComputeJacobianColor()
 40: @*/
 41: PetscErrorCode SNESDefaultComputeJacobian(SNES snes,Vec x1,Mat *J,Mat *B,MatStructure *flag,void *ctx)
 42: {
 43:   Vec            j1a,j2a,x2;
 45:   PetscInt       i,N,start,end,j;
 46:   PetscScalar    dx,mone = -1.0,*y,scale,*xx,wscale;
 47:   PetscReal      amax,epsilon = PETSC_SQRT_MACHINE_EPSILON;
 48:   PetscReal      dx_min = 1.e-16,dx_par = 1.e-1;
 49:   MPI_Comm       comm;
 50:   PetscErrorCode (*eval_fct)(SNES,Vec,Vec)=0;
 51:   PetscTruth     assembled;

 54:   PetscOptionsGetReal(snes->prefix,"-snes_test_err",&epsilon,0);
 55:   eval_fct = SNESComputeFunction;

 57:   PetscObjectGetComm((PetscObject)x1,&comm);
 58:   MatAssembled(*B,&assembled);
 59:   if (assembled) {
 60:     MatZeroEntries(*B);
 61:   }
 62:   if (!snes->nvwork) {
 63:     VecDuplicateVecs(x1,3,&snes->vwork);
 64:     snes->nvwork = 3;
 65:     PetscLogObjectParents(snes,3,snes->vwork);
 66:   }
 67:   j1a = snes->vwork[0]; j2a = snes->vwork[1]; x2 = snes->vwork[2];

 69:   VecGetSize(x1,&N);
 70:   VecGetOwnershipRange(x1,&start,&end);
 71:   (*eval_fct)(snes,x1,j1a);

 73:   /* Compute Jacobian approximation, 1 column at a time. 
 74:       x1 = current iterate, j1a = F(x1)
 75:       x2 = perturbed iterate, j2a = F(x2)
 76:    */
 77:   for (i=0; i<N; i++) {
 78:     VecCopy(x1,x2);
 79:     if (i>= start && i<end) {
 80:       VecGetArray(x1,&xx);
 81:       dx = xx[i-start];
 82:       VecRestoreArray(x1,&xx);
 83: #if !defined(PETSC_USE_COMPLEX)
 84:       if (dx < dx_min && dx >= 0.0) dx = dx_par;
 85:       else if (dx < 0.0 && dx > -dx_min) dx = -dx_par;
 86: #else
 87:       if (PetscAbsScalar(dx) < dx_min && PetscRealPart(dx) >= 0.0) dx = dx_par;
 88:       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < dx_min) dx = -dx_par;
 89: #endif
 90:       dx *= epsilon;
 91:       wscale = 1.0/dx;
 92:       VecSetValues(x2,1,&i,&dx,ADD_VALUES);
 93:     } else {
 94:       wscale = 0.0;
 95:     }
 96:     (*eval_fct)(snes,x2,j2a);
 97:     VecAXPY(&mone,j1a,j2a);
 98:     /* Communicate scale to all processors */
 99:     MPI_Allreduce(&wscale,&scale,1,MPIU_SCALAR,PetscSum_Op,comm);
100:     VecScale(&scale,j2a);
101:     VecNorm(j2a,NORM_INFINITY,&amax); amax *= 1.e-14;
102:     VecGetArray(j2a,&y);
103:     for (j=start; j<end; j++) {
104:       if (PetscAbsScalar(y[j-start]) > amax) {
105:         MatSetValues(*B,1,&j,1,&i,y+j-start,INSERT_VALUES);
106:       }
107:     }
108:     VecRestoreArray(j2a,&y);
109:   }
110:   MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);
111:   MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);
112:   *flag =  DIFFERENT_NONZERO_PATTERN;
113:   return(0);
114: }