111320018SBarry Smith 211320018SBarry Smith #ifndef lint 3*0521c3abSLois Curfman McInnes static char vcid[] = "$Id: snesj.c,v 1.25 1996/01/11 20:14:56 bsmith Exp curfman $"; 411320018SBarry Smith #endif 511320018SBarry Smith 6b1f0a012SBarry Smith #include "draw.h" /*I "draw.h" I*/ 7*0521c3abSLois Curfman McInnes #include "snesimpl.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 @*/ 365334005bSBarry 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; 415334005bSBarry Smith double amax, epsilon = 1.e-8; /* assumes double precision */ 42bbb6d6a8SBarry Smith MPI_Comm comm; 43*0521c3abSLois Curfman McInnes int (*eval_fct)(SNES,Vec,Vec); 44*0521c3abSLois Curfman McInnes 45*0521c3abSLois Curfman McInnes if (snes->method_class != SNES_NONLINEAR_EQUATIONS) 46*0521c3abSLois Curfman McInnes eval_fct = SNESComputeFunction; 47*0521c3abSLois Curfman McInnes else if (snes->method_class != SNES_UNCONSTRAINED_MINIMIZATION) 48*0521c3abSLois Curfman McInnes eval_fct = SNESComputeGradient; 49*0521c3abSLois Curfman McInnes else SETERRQ(1,"SNESDefaultComputeJacobian: Invalid method class"); 5023242f5aSBarry Smith 51bbb6d6a8SBarry Smith PetscObjectGetComm((PetscObject)x1,&comm); 52336a5e98SBarry Smith MatZeroEntries(*J); 5378b31e54SBarry Smith ierr = VecDuplicate(x1,&j1); CHKERRQ(ierr); 5478b31e54SBarry Smith ierr = VecDuplicate(x1,&j2); CHKERRQ(ierr); 5578b31e54SBarry Smith ierr = VecDuplicate(x1,&x2); CHKERRQ(ierr); 56d370d78aSBarry Smith PLogObjectParent(snes,j1); PLogObjectParent(snes,j2); 57393d2d9aSLois Curfman McInnes PLogObjectParent(snes,x2); 5823242f5aSBarry Smith 5978b31e54SBarry Smith ierr = VecGetSize(x1,&N); CHKERRQ(ierr); 6078b31e54SBarry Smith ierr = VecGetOwnershipRange(x1,&start,&end); CHKERRQ(ierr); 6139e2f89bSBarry Smith VecGetArray(x1,&xx); 62*0521c3abSLois Curfman McInnes ierr = eval_fct(snes,x1,j1); CHKERRQ(ierr); 6339e2f89bSBarry Smith for ( i=0; i<N; i++ ) { 6478b31e54SBarry Smith ierr = VecCopy(x1,x2); CHKERRQ(ierr); 6523242f5aSBarry Smith if ( i>= start && i<end) { 6639e2f89bSBarry Smith dx = xx[i-start]; 6719a167f6SBarry Smith #if !defined(PETSC_COMPLEX) 68336a5e98SBarry Smith if (dx < 1.e-16 && dx >= 0.0) dx = 1.e-1; 69336a5e98SBarry Smith else if (dx < 0.0 && dx > -1.e-16) dx = -1.e-1; 7019a167f6SBarry Smith #else 7119a167f6SBarry Smith if (abs(dx) < 1.e-16 && real(dx) >= 0.0) dx = 1.e-1; 72ec12a082SBarry Smith else if (real(dx) < 0.0 && abs(dx) < 1.e-16) dx = -1.e-1; 7319a167f6SBarry Smith #endif 7439e2f89bSBarry Smith dx *= epsilon; 75bbb6d6a8SBarry Smith wscale = -1.0/dx; 76dbb450caSBarry Smith VecSetValues(x2,1,&i,&dx,ADD_VALUES); 7711320018SBarry Smith } 78bbb6d6a8SBarry Smith else { 79bbb6d6a8SBarry Smith wscale = 0.0; 80bbb6d6a8SBarry Smith } 81*0521c3abSLois Curfman McInnes ierr = eval_fct(snes,x2,j2); CHKERRQ(ierr); 8278b31e54SBarry Smith ierr = VecAXPY(&mone,j1,j2); CHKERRQ(ierr); 83bbb6d6a8SBarry Smith /* communicate scale to all processors */ 84bbb6d6a8SBarry Smith #if !defined(PETSC_COMPLEX) 85bbb6d6a8SBarry Smith MPI_Allreduce(&wscale,&scale,1,MPI_DOUBLE,MPI_SUM,comm); 86bbb6d6a8SBarry Smith #else 87bbb6d6a8SBarry Smith MPI_Allreduce(&wscale,&scale,2,MPI_DOUBLE,MPI_SUM,comm); 88bbb6d6a8SBarry Smith #endif 895334005bSBarry Smith scale = -scale; 9023242f5aSBarry Smith VecScale(&scale,j2); 9123242f5aSBarry Smith VecGetArray(j2,&y); 92cddf8d76SBarry Smith VecNorm(j2,NORM_INFINITY,&amax); amax *= 1.e-14; 9323242f5aSBarry Smith for ( j=start; j<end; j++ ) { 94cddf8d76SBarry Smith if (PetscAbsScalar(y[j-start]) > amax) { 95dbb450caSBarry Smith ierr = MatSetValues(*J,1,&j,1,&i,y+j-start,INSERT_VALUES); CHKERRQ(ierr); 9623242f5aSBarry Smith } 9723242f5aSBarry Smith } 9823242f5aSBarry Smith VecRestoreArray(j2,&y); 9923242f5aSBarry Smith } 100ee50ffe9SBarry Smith MatAssemblyBegin(*J,FINAL_ASSEMBLY); 10123242f5aSBarry Smith VecDestroy(x2); VecDestroy(j1); VecDestroy(j2); 102ee50ffe9SBarry Smith MatAssemblyEnd(*J,FINAL_ASSEMBLY); 10311320018SBarry Smith return 0; 10411320018SBarry Smith } 10511320018SBarry Smith 106*0521c3abSLois Curfman McInnes /*@C 107*0521c3abSLois Curfman McInnes SNESDefaultComputeHessian - Computes the Hessian using finite 108*0521c3abSLois Curfman McInnes differences. 109*0521c3abSLois Curfman McInnes 110*0521c3abSLois Curfman McInnes Input Parameters: 111*0521c3abSLois Curfman McInnes . x1 - compute Hessian at this point 112*0521c3abSLois Curfman McInnes . ctx - application's gradient context, as set with SNESSetGradient() 113*0521c3abSLois Curfman McInnes 114*0521c3abSLois Curfman McInnes Output Parameters: 115*0521c3abSLois Curfman McInnes . J - Hessian 116*0521c3abSLois Curfman McInnes . B - preconditioner, same as Hessian 117*0521c3abSLois Curfman McInnes . flag - matrix flag 118*0521c3abSLois Curfman McInnes 119*0521c3abSLois Curfman McInnes Options Database Key: 120*0521c3abSLois Curfman McInnes $ -snes_fd 121*0521c3abSLois Curfman McInnes 122*0521c3abSLois Curfman McInnes Notes: 123*0521c3abSLois Curfman McInnes This routine is slow and expensive, and is not currently optimized 124*0521c3abSLois Curfman McInnes to take advantage of sparsity in the problem. Although 125*0521c3abSLois Curfman McInnes SNESDefaultComputeHessian() is not recommended for general use 126*0521c3abSLois Curfman McInnes in large-scale applications, It can be useful in checking the 127*0521c3abSLois Curfman McInnes correctness of a user-provided Hessian. 128*0521c3abSLois Curfman McInnes 129*0521c3abSLois Curfman McInnes .keywords: SNES, finite differences, Hessian 130*0521c3abSLois Curfman McInnes 131*0521c3abSLois Curfman McInnes .seealso: SNESSetHessian(), SNESTestHessian() 132*0521c3abSLois Curfman McInnes @*/ 133*0521c3abSLois Curfman McInnes int SNESDefaultComputeHessian(SNES snes,Vec x1,Mat *J,Mat *B,MatStructure *flag,void *ctx) 134*0521c3abSLois Curfman McInnes { 135*0521c3abSLois Curfman McInnes return SNESDefaultComputeJacobian(snes,x1,J,B,flag,ctx); 136*0521c3abSLois Curfman McInnes } 137