Actual source code: snesj.c

  1: /*$Id: snesj.c,v 1.71 2001/03/23 23:24:07 balay Exp $*/

  3: #include "src/snes/snesimpl.h"    /*I  "petscsnes.h"  I*/

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

  8:    Collective on SNES

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

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

 19:    Options Database Key:
 20: +  -snes_fd - Activates SNESDefaultComputeJacobian()
 21: -  -snes_test_err - Square root of function error tolerance, default 1.e-8

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

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

 33:    Level: intermediate

 35: .keywords: SNES, finite differences, Jacobian

 37: .seealso: SNESSetJacobian(), SNESDefaultComputeJacobianColor()
 38: @*/
 39: int SNESDefaultComputeJacobian(SNES snes,Vec x1,Mat *J,Mat *B,MatStructure *flag,void *ctx)
 40: {
 41:   Vec       j1a,j2a,x2;
 42:   int       i,ierr,N,start,end,j;
 43:   Scalar    dx,mone = -1.0,*y,scale,*xx,wscale;
 44:   PetscReal amax,epsilon = 1.e-8; /* assumes PetscReal precision */
 45:   PetscReal dx_min = 1.e-16,dx_par = 1.e-1;
 46:   MPI_Comm  comm;
 47:   int      (*eval_fct)(SNES,Vec,Vec)=0;

 50:   PetscOptionsGetDouble(snes->prefix,"-snes_test_err",&epsilon,0);
 51:   if (snes->method_class == SNES_NONLINEAR_EQUATIONS) eval_fct = SNESComputeFunction;
 52:   else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) eval_fct = SNESComputeGradient;
 53:   else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Invalid method class");

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

 64:   VecGetSize(x1,&N);
 65:   VecGetOwnershipRange(x1,&start,&end);
 66:   (*eval_fct)(snes,x1,j1a);

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

111: /*@C
112:    SNESDefaultComputeHessian - Computes the Hessian using finite differences. 

114:    Collective on SNES

116:    Input Parameters:
117: +  x1 - compute Hessian at this point
118: -  ctx - application's gradient context, as set with SNESSetGradient()

120:    Output Parameters:
121: +  J - Hessian matrix (not altered in this routine)
122: .  B - newly computed Hessian matrix to use with preconditioner (generally the same as J)
123: -  flag - flag indicating whether the matrix sparsity structure has changed

125:    Options Database Key:
126: $  -snes_fd - Activates SNESDefaultComputeHessian()


129:    Level: intermediate

131:    Notes:
132:    This routine is slow and expensive, and is not currently optimized
133:    to take advantage of sparsity in the problem.  Although
134:    SNESDefaultComputeHessian() is not recommended for general use
135:    in large-scale applications, It can be useful in checking the
136:    correctness of a user-provided Hessian.

138: .keywords: SNES, finite differences, Hessian

140: .seealso: SNESSetHessian()
141: @*/
142: int SNESDefaultComputeHessian(SNES snes,Vec x1,Mat *J,Mat *B,MatStructure *flag,void *ctx)
143: {

147:   SNESDefaultComputeJacobian(snes,x1,J,B,flag,ctx);
148:   return(0);
149: }

151: /*@C
152:    SNESDefaultComputeHessianColor - Computes the Hessian using colored finite differences. 

154:    Collective on SNES

156:    Input Parameters:
157: +  x1 - compute Hessian at this point
158: -  ctx - application's gradient context, as set with SNESSetGradient()

160:    Output Parameters:
161: +  J - Hessian matrix (not altered in this routine)
162: .  B - newly computed Hessian matrix to use with preconditioner (generally the same as J)
163: -  flag - flag indicating whether the matrix sparsity structure has changed

165:     Options Database Keys:
166: .  -mat_fd_coloring_freq <freq> - Activates SNESDefaultComputeJacobianColor()

168:    Level: intermediate

170:  .keywords: SNES, finite differences, Hessian, coloring, sparse

172: .seealso: SNESSetHessian()
173: @*/
174: int SNESDefaultComputeHessianColor(SNES snes,Vec x1,Mat *J,Mat *B,MatStructure *flag,void *ctx)
175: {

179:   SNESDefaultComputeJacobianColor(snes,x1,J,B,flag,ctx);
180:   return(0);
181: }