xref: /petsc/src/snes/interface/snesj.c (revision 5334005bcaa1d066a84180769b32245968508082)
111320018SBarry Smith 
211320018SBarry Smith #ifndef lint
3*5334005bSBarry Smith static char vcid[] = "$Id: snesj.c,v 1.24 1995/11/01 19:12:03 bsmith Exp bsmith $";
411320018SBarry Smith #endif
511320018SBarry Smith 
6b1f0a012SBarry Smith #include "draw.h"    /*I  "draw.h"  I*/
7b1f0a012SBarry Smith #include "snes.h"    /*I  "snes.h"  I*/
811320018SBarry Smith 
94b828684SBarry Smith /*@C
105f3c43d9SLois Curfman McInnes    SNESDefaultComputeJacobian - Computes the Jacobian using finite
115f3c43d9SLois Curfman McInnes    differences.
1211320018SBarry Smith 
1311320018SBarry Smith    Input Parameters:
14da88328cSLois Curfman McInnes .  x1 - compute Jacobian at this point
15da88328cSLois Curfman McInnes .  ctx - application's function context, as set with SNESSetFunction()
1611320018SBarry Smith 
1711320018SBarry Smith    Output Parameters:
1823242f5aSBarry Smith .  J - Jacobian
1923242f5aSBarry Smith .  B - preconditioner, same as Jacobian
20da88328cSLois Curfman McInnes .  flag - matrix flag
2111320018SBarry Smith 
22ad960d00SLois Curfman McInnes    Options Database Key:
23ad960d00SLois Curfman McInnes $  -snes_fd
24ad960d00SLois Curfman McInnes 
255f3c43d9SLois Curfman McInnes    Notes:
265f3c43d9SLois Curfman McInnes    This routine is slow and expensive, and is not currently optimized
275f3c43d9SLois Curfman McInnes    to take advantage of sparsity in the problem.  Although
285f3c43d9SLois Curfman McInnes    SNESDefaultComputeJacobian() is not recommended for general use
295f3c43d9SLois Curfman McInnes    in large-scale applications, It can be useful in checking the
305f3c43d9SLois Curfman McInnes    correctness of a user-provided Jacobian.
3111320018SBarry Smith 
325f3c43d9SLois Curfman McInnes .keywords: SNES, finite differences, Jacobian
335f3c43d9SLois Curfman McInnes 
345f3c43d9SLois Curfman McInnes .seealso: SNESSetJacobian(), SNESTestJacobian()
3511320018SBarry Smith @*/
36*5334005bSBarry Smith int SNESDefaultComputeJacobian(SNES snes,Vec x1,Mat *J,Mat *B,MatStructure *flag,void *ctx)
3711320018SBarry Smith {
3823242f5aSBarry Smith   Vec      j1,j2,x2;
3923242f5aSBarry Smith   int      i,ierr,N,start,end,j;
40bbb6d6a8SBarry Smith   Scalar   dx, mone = -1.0,*y,scale,*xx,wscale;
41*5334005bSBarry Smith   double   amax, epsilon = 1.e-8; /* assumes double precision */
42bbb6d6a8SBarry Smith   MPI_Comm comm;
4323242f5aSBarry Smith 
44bbb6d6a8SBarry Smith   PetscObjectGetComm((PetscObject)x1,&comm);
45336a5e98SBarry Smith   MatZeroEntries(*J);
4678b31e54SBarry Smith   ierr = VecDuplicate(x1,&j1); CHKERRQ(ierr);
4778b31e54SBarry Smith   ierr = VecDuplicate(x1,&j2); CHKERRQ(ierr);
4878b31e54SBarry Smith   ierr = VecDuplicate(x1,&x2); CHKERRQ(ierr);
49d370d78aSBarry Smith   PLogObjectParent(snes,j1); PLogObjectParent(snes,j2);
50393d2d9aSLois Curfman McInnes   PLogObjectParent(snes,x2);
5123242f5aSBarry Smith 
5278b31e54SBarry Smith   ierr = VecGetSize(x1,&N); CHKERRQ(ierr);
5378b31e54SBarry Smith   ierr = VecGetOwnershipRange(x1,&start,&end); CHKERRQ(ierr);
5439e2f89bSBarry Smith   VecGetArray(x1,&xx);
5578b31e54SBarry Smith   ierr = SNESComputeFunction(snes,x1,j1); CHKERRQ(ierr);
5639e2f89bSBarry Smith   for ( i=0; i<N; i++ ) {
5778b31e54SBarry Smith     ierr = VecCopy(x1,x2); CHKERRQ(ierr);
5823242f5aSBarry Smith     if ( i>= start && i<end) {
5939e2f89bSBarry Smith       dx = xx[i-start];
6019a167f6SBarry Smith #if !defined(PETSC_COMPLEX)
61336a5e98SBarry Smith       if (dx < 1.e-16 && dx >= 0.0) dx = 1.e-1;
62336a5e98SBarry Smith       else if (dx < 0.0 && dx > -1.e-16) dx = -1.e-1;
6319a167f6SBarry Smith #else
6419a167f6SBarry Smith       if (abs(dx) < 1.e-16 && real(dx) >= 0.0) dx = 1.e-1;
65ec12a082SBarry Smith       else if (real(dx) < 0.0 && abs(dx) < 1.e-16) dx = -1.e-1;
6619a167f6SBarry Smith #endif
6739e2f89bSBarry Smith       dx *= epsilon;
68bbb6d6a8SBarry Smith       wscale = -1.0/dx;
69dbb450caSBarry Smith       VecSetValues(x2,1,&i,&dx,ADD_VALUES);
7011320018SBarry Smith     }
71bbb6d6a8SBarry Smith     else {
72bbb6d6a8SBarry Smith       wscale = 0.0;
73bbb6d6a8SBarry Smith     }
7478b31e54SBarry Smith     ierr = SNESComputeFunction(snes,x2,j2); CHKERRQ(ierr);
7578b31e54SBarry Smith     ierr = VecAXPY(&mone,j1,j2); CHKERRQ(ierr);
76bbb6d6a8SBarry Smith /* communicate scale to all processors */
77bbb6d6a8SBarry Smith #if !defined(PETSC_COMPLEX)
78bbb6d6a8SBarry Smith     MPI_Allreduce(&wscale,&scale,1,MPI_DOUBLE,MPI_SUM,comm);
79bbb6d6a8SBarry Smith #else
80bbb6d6a8SBarry Smith     MPI_Allreduce(&wscale,&scale,2,MPI_DOUBLE,MPI_SUM,comm);
81bbb6d6a8SBarry Smith #endif
82*5334005bSBarry Smith     scale = -scale;
8323242f5aSBarry Smith     VecScale(&scale,j2);
8423242f5aSBarry Smith     VecGetArray(j2,&y);
85cddf8d76SBarry Smith     VecNorm(j2,NORM_INFINITY,&amax); amax *= 1.e-14;
8623242f5aSBarry Smith     for ( j=start; j<end; j++ ) {
87cddf8d76SBarry Smith       if (PetscAbsScalar(y[j-start]) > amax) {
88dbb450caSBarry Smith         ierr = MatSetValues(*J,1,&j,1,&i,y+j-start,INSERT_VALUES); CHKERRQ(ierr);
8923242f5aSBarry Smith       }
9023242f5aSBarry Smith     }
9123242f5aSBarry Smith     VecRestoreArray(j2,&y);
9223242f5aSBarry Smith   }
93ee50ffe9SBarry Smith   MatAssemblyBegin(*J,FINAL_ASSEMBLY);
9423242f5aSBarry Smith   VecDestroy(x2); VecDestroy(j1); VecDestroy(j2);
95ee50ffe9SBarry Smith   MatAssemblyEnd(*J,FINAL_ASSEMBLY);
9611320018SBarry Smith   return 0;
9711320018SBarry Smith }
9811320018SBarry Smith 
99