Actual source code: snestest.c

  1: #define PETSCSNES_DLL

 3:  #include private/snesimpl.h

  5: typedef struct {
  6:   PetscTruth complete_print;
  7: } SNES_Test;

  9: /*
 10:      SNESSolve_Test - Tests whether a hand computed Jacobian 
 11:      matches one compute via finite differences.
 12: */
 15: PetscErrorCode SNESSolve_Test(SNES snes)
 16: {
 17:   Mat            A = snes->jacobian,B;
 18:   Vec            x = snes->vec_sol,f = snes->vec_func;
 20:   PetscInt       i;
 21:   MatStructure   flg;
 22:   PetscReal      nrm,gnorm;
 23:   SNES_Test      *neP = (SNES_Test*)snes->data;


 27:   if (A != snes->jacobian_pre) {
 28:     SETERRQ(PETSC_ERR_ARG_WRONG,"Cannot test with alternative preconditioner");
 29:   }

 31:   PetscPrintf(((PetscObject)snes)->comm,"Testing hand-coded Jacobian, if the ratio is\n");
 32:   PetscPrintf(((PetscObject)snes)->comm,"O(1.e-8), the hand-coded Jacobian is probably correct.\n");
 33:   if (!neP->complete_print) {
 34:     PetscPrintf(((PetscObject)snes)->comm,"Run with -snes_test_display to show difference\n");
 35:     PetscPrintf(((PetscObject)snes)->comm,"of hand-coded and finite difference Jacobian.\n");
 36:   }

 38:   for (i=0; i<3; i++) {
 39:     if (i == 1) {VecSet(x,-1.0);}
 40:     else if (i == 2) {VecSet(x,1.0);}

 42:     /* evaluate the function at this point because SNESDefaultComputeJacobianColor() assumes that the function has been evaluated and put into snes->vec_func */
 43:     SNESComputeFunction(snes,x,f);

 45:     /* compute both versions of Jacobian */
 46:     SNESComputeJacobian(snes,x,&A,&A,&flg);
 47:     if (!i) {MatConvert(A,MATSAME,MAT_INITIAL_MATRIX,&B);}
 48:     SNESDefaultComputeJacobian(snes,x,&B,&B,&flg,snes->funP);
 49:     if (neP->complete_print) {
 50:       MPI_Comm    comm;
 51:       PetscViewer viewer;
 52:       PetscPrintf(((PetscObject)snes)->comm,"Finite difference Jacobian\n");
 53:       PetscObjectGetComm((PetscObject)B,&comm);
 54:       PetscViewerASCIIGetStdout(comm,&viewer);
 55:       MatView(B,viewer);
 56:     }
 57:     /* compare */
 58:     MatAYPX(B,-1.0,A,DIFFERENT_NONZERO_PATTERN);
 59:     MatNorm(B,NORM_FROBENIUS,&nrm);
 60:     MatNorm(A,NORM_FROBENIUS,&gnorm);
 61:     if (neP->complete_print) {
 62:       MPI_Comm    comm;
 63:       PetscViewer viewer;
 64:       PetscPrintf(((PetscObject)snes)->comm,"Hand-coded Jacobian\n");
 65:       PetscObjectGetComm((PetscObject)B,&comm);
 66:       PetscViewerASCIIGetStdout(comm,&viewer);
 67:       MatView(A,viewer);
 68:       PetscPrintf(((PetscObject)snes)->comm,"Hand-coded minus finite difference Jacobian\n");
 69:       MatView(B,viewer);
 70:     }
 71:     if (!gnorm) gnorm = 1; /* just in case */
 72:     PetscPrintf(((PetscObject)snes)->comm,"Norm of matrix ratio %G difference %G\n",nrm/gnorm,nrm);
 73:   }
 74:   MatDestroy(B);
 75:   /*
 76:          Return error code cause Jacobian not good
 77:   */
 78:   PetscFunctionReturn(PETSC_ERR_ARG_WRONGSTATE);
 79: }
 80: /* ------------------------------------------------------------ */
 83: PetscErrorCode SNESDestroy_Test(SNES snes)
 84: {
 87:   PetscFree(snes->data);
 88:   return(0);
 89: }

 93: static PetscErrorCode SNESSetFromOptions_Test(SNES snes)
 94: {
 95:   SNES_Test      *ls = (SNES_Test *)snes->data;


100:   PetscOptionsHead("Hand-coded Jacobian tester options");
101:   PetscOptionsTruth("-snes_test_display","Display difference between hand-coded and finite difference Jacobians","None",ls->complete_print,&ls->complete_print,PETSC_NULL);
102:   PetscOptionsTail();
103:   return(0);
104: }

106: /* ------------------------------------------------------------ */
107: /*MC
108:       SNESTEST - Test hand-coded Jacobian against finite difference Jacobian

110:    Options Database:
111: .    -snes_test_display  Display difference between approximate and hand-coded Jacobian

113:    Level: intermediate

115: .seealso:  SNESCreate(), SNES, SNESSetType(), SNESLS, SNESTR

117: M*/
121: PetscErrorCode  SNESCreate_Test(SNES  snes)
122: {
123:   SNES_Test      *neP;

127:   snes->ops->setup             = 0;
128:   snes->ops->solve             = SNESSolve_Test;
129:   snes->ops->destroy             = SNESDestroy_Test;
130:   snes->ops->setfromoptions  = SNESSetFromOptions_Test;
131:   snes->ops->view            = 0;

133:   ierr                        = PetscNewLog(snes,SNES_Test,&neP);
134:   snes->data            = (void*)neP;
135:   neP->complete_print   = PETSC_FALSE;
136:   return(0);
137: }