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: }