static char help[] = "Newton method to solve u'' + u^{2} = f, sequentially.\n\ This example employs a user-defined reasonview routine.\n\n"; #include /* User-defined routines */ PETSC_EXTERN PetscErrorCode FormJacobian(SNES,Vec,Mat,Mat,void*); PETSC_EXTERN PetscErrorCode FormFunction(SNES,Vec,Vec,void*); PETSC_EXTERN PetscErrorCode FormInitialGuess(Vec); PETSC_EXTERN PetscErrorCode MySNESConvergedReasonView(SNES,void*); PETSC_EXTERN PetscErrorCode MyKSPConvergedReasonView(KSP,void*); /* User-defined context for monitoring */ typedef struct { PetscViewer viewer; } ReasonViewCtx; int main(int argc,char **argv) { SNES snes; /* SNES context */ KSP ksp; /* KSP context */ Vec x,r,F,U; /* vectors */ Mat J; /* Jacobian matrix */ ReasonViewCtx monP; /* monitoring context */ PetscInt its,n = 5,i; PetscMPIInt size; PetscScalar h,xp,v; MPI_Comm comm; PetscFunctionBeginUser; PetscCall(PetscInitialize(&argc,&argv,(char*)0,help)); PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size)); PetscCheck(size == 1,PETSC_COMM_SELF,PETSC_ERR_WRONG_MPI_SIZE,"This is a uniprocessor example only!"); PetscCall(PetscOptionsGetInt(NULL,NULL,"-n",&n,NULL)); h = 1.0/(n-1); comm = PETSC_COMM_WORLD; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create nonlinear solver context - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ PetscCall(SNESCreate(comm,&snes)); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create vector data structures; set function evaluation routine - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Note that we form 1 vector from scratch and then duplicate as needed. */ PetscCall(VecCreate(comm,&x)); PetscCall(VecSetSizes(x,PETSC_DECIDE,n)); PetscCall(VecSetFromOptions(x)); PetscCall(VecDuplicate(x,&r)); PetscCall(VecDuplicate(x,&F)); PetscCall(VecDuplicate(x,&U)); /* Set function evaluation routine and vector */ PetscCall(SNESSetFunction(snes,r,FormFunction,(void*)F)); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create matrix data structure; set Jacobian evaluation routine - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ PetscCall(MatCreate(comm,&J)); PetscCall(MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,n,n)); PetscCall(MatSetFromOptions(J)); PetscCall(MatSeqAIJSetPreallocation(J,3,NULL)); /* Set Jacobian matrix data structure and default Jacobian evaluation routine. User can override with: -snes_fd : default finite differencing approximation of Jacobian -snes_mf : matrix-free Newton-Krylov method with no preconditioning (unless user explicitly sets preconditioner) -snes_mf_operator : form preconditioning matrix as set by the user, but use matrix-free approx for Jacobian-vector products within Newton-Krylov method */ PetscCall(SNESSetJacobian(snes,J,J,FormJacobian,NULL)); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Customize nonlinear solver; set runtime options - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Set an optional user-defined reasonview routine */ PetscCall(PetscViewerASCIIGetStdout(comm,&monP.viewer)); /* Just make sure we can not repeat addding the same function * PETSc will be able to igore the repeated function */ for (i=0; i<4; i++) { PetscCall(SNESConvergedReasonViewSet(snes,MySNESConvergedReasonView,&monP,0)); } PetscCall(SNESGetKSP(snes,&ksp)); /* Just make sure we can not repeat addding the same function * PETSc will be able to igore the repeated function */ for (i=0; i<4; i++) { PetscCall(KSPConvergedReasonViewSet(ksp,MyKSPConvergedReasonView,&monP,0)); } /* Set SNES/KSP/KSP/PC runtime options, e.g., -snes_view -snes_monitor -ksp_type -pc_type */ PetscCall(SNESSetFromOptions(snes)); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Initialize application: Store right-hand-side of PDE and exact solution - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ xp = 0.0; for (i=0; iviewer; SNESConvergedReason reason; const char *strreason; PetscCall(SNESGetConvergedReason(snes,&reason)); PetscCall(SNESGetConvergedReasonString(snes,&strreason)); PetscCall(PetscViewerASCIIPrintf(viewer,"Customized SNES converged reason view\n")); PetscCall(PetscViewerASCIIAddTab(viewer,1)); if (reason > 0) { PetscCall(PetscViewerASCIIPrintf(viewer,"Converged due to %s\n",strreason)); } else if (reason <= 0) { PetscCall(PetscViewerASCIIPrintf(viewer,"Did not converge due to %s\n",strreason)); } PetscCall(PetscViewerASCIISubtractTab(viewer,1)); return 0; } PetscErrorCode MyKSPConvergedReasonView(KSP ksp,void *ctx) { ReasonViewCtx *monP = (ReasonViewCtx*) ctx; PetscViewer viewer = monP->viewer; KSPConvergedReason reason; const char *reasonstr; PetscCall(KSPGetConvergedReason(ksp,&reason)); PetscCall(KSPGetConvergedReasonString(ksp,&reasonstr)); PetscCall(PetscViewerASCIIAddTab(viewer,2)); PetscCall(PetscViewerASCIIPrintf(viewer,"Customized KSP converged reason view\n")); PetscCall(PetscViewerASCIIAddTab(viewer,1)); if (reason > 0) { PetscCall(PetscViewerASCIIPrintf(viewer,"Converged due to %s\n",reasonstr)); } else if (reason <= 0) { PetscCall(PetscViewerASCIIPrintf(viewer,"Did not converge due to %s\n",reasonstr)); } PetscCall(PetscViewerASCIISubtractTab(viewer,3)); return 0; } /*TEST test: suffix: 1 nsize: 1 filter: sed -e "s/CONVERGED_ATOL/CONVERGED_RTOL/g" test: suffix: 2 nsize: 1 args: -ksp_converged_reason_view_cancel filter: sed -e "s/CONVERGED_ATOL/CONVERGED_RTOL/g" test: suffix: 3 nsize: 1 args: -ksp_converged_reason_view_cancel -ksp_converged_reason filter: sed -e "s/CONVERGED_ATOL/CONVERGED_RTOL/g" test: suffix: 4 nsize: 1 args: -snes_converged_reason_view_cancel filter: sed -e "s/CONVERGED_ATOL/CONVERGED_RTOL/g" test: suffix: 5 nsize: 1 args: -snes_converged_reason_view_cancel -snes_converged_reason filter: sed -e "s/CONVERGED_ATOL/CONVERGED_RTOL/g" TEST*/