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