1 2 #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/ 3 4 /*@ 5 SNESApplyNPC - Calls SNESSolve() on preconditioner for the SNES 6 7 Collective on SNES 8 9 Input Parameters: 10 + snes - the SNES context 11 . x - input vector 12 - f - optional; the function evaluation on x 13 14 Output Parameter: 15 . y - function vector, as set by SNESSetFunction() 16 17 Notes: 18 SNESComputeFunction() should be called on x before SNESApplyNPC() is called, as it is 19 with SNESComuteJacobian(). 20 21 Level: developer 22 23 .seealso: SNESGetNPC(),SNESSetNPC(),SNESComputeFunction() 24 @*/ 25 PetscErrorCode SNESApplyNPC(SNES snes,Vec x,Vec f,Vec y) 26 { 27 PetscErrorCode ierr; 28 29 PetscFunctionBegin; 30 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 31 PetscValidHeaderSpecific(x,VEC_CLASSID,2); 32 PetscValidHeaderSpecific(y,VEC_CLASSID,4); 33 PetscCheckSameComm(snes,1,x,2); 34 PetscCheckSameComm(snes,1,y,4); 35 ierr = VecValidValues(x,2,PETSC_TRUE);CHKERRQ(ierr); 36 if (snes->npc) { 37 if (f) { 38 ierr = SNESSetInitialFunction(snes->npc,f);CHKERRQ(ierr); 39 } 40 ierr = VecCopy(x,y);CHKERRQ(ierr); 41 ierr = PetscLogEventBegin(SNES_NPCSolve,snes->npc,x,y,0);CHKERRQ(ierr); 42 ierr = SNESSolve(snes->npc,snes->vec_rhs,y);CHKERRQ(ierr); 43 ierr = PetscLogEventEnd(SNES_NPCSolve,snes->npc,x,y,0);CHKERRQ(ierr); 44 ierr = VecAYPX(y,-1.0,x);CHKERRQ(ierr); 45 PetscFunctionReturn(0); 46 } 47 PetscFunctionReturn(0); 48 } 49 50 PetscErrorCode SNESComputeFunctionDefaultNPC(SNES snes,Vec X,Vec F) 51 { 52 /* This is to be used as an argument to SNESMF -- NOT as a "function" */ 53 SNESConvergedReason reason; 54 PetscErrorCode ierr; 55 56 PetscFunctionBegin; 57 if (snes->npc) { 58 ierr = SNESApplyNPC(snes,X,NULL,F);CHKERRQ(ierr); 59 ierr = SNESGetConvergedReason(snes->npc,&reason);CHKERRQ(ierr); 60 if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 61 ierr = SNESSetFunctionDomainError(snes);CHKERRQ(ierr); 62 } 63 } else { 64 ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 65 } 66 PetscFunctionReturn(0); 67 } 68 69 /*@ 70 SNESGetNPCFunction - Gets the function from a preconditioner after SNESSolve() has been called. 71 72 Collective on SNES 73 74 Input Parameters: 75 . snes - the SNES context 76 77 Output Parameter: 78 + F - function vector 79 - fnorm - the norm of F 80 81 Level: developer 82 83 .seealso: SNESGetNPC(),SNESSetNPC(),SNESComputeFunction(),SNESApplyNPC(),SNESSolve() 84 @*/ 85 PetscErrorCode SNESGetNPCFunction(SNES snes,Vec F,PetscReal *fnorm) 86 { 87 PetscErrorCode ierr; 88 PCSide npcside; 89 SNESFunctionType functype; 90 SNESNormSchedule normschedule; 91 Vec FPC,XPC; 92 93 PetscFunctionBegin; 94 if (snes->npc) { 95 ierr = SNESGetNPCSide(snes->npc,&npcside);CHKERRQ(ierr); 96 ierr = SNESGetFunctionType(snes->npc,&functype);CHKERRQ(ierr); 97 ierr = SNESGetNormSchedule(snes->npc,&normschedule);CHKERRQ(ierr); 98 99 /* check if the function is valid based upon how the inner solver is preconditioned */ 100 if (normschedule != SNES_NORM_NONE && normschedule != SNES_NORM_INITIAL_ONLY && (npcside == PC_RIGHT || functype == SNES_FUNCTION_UNPRECONDITIONED)) { 101 ierr = SNESGetFunction(snes->npc,&FPC,NULL,NULL);CHKERRQ(ierr); 102 if (FPC) { 103 if (fnorm) {ierr = VecNorm(FPC,NORM_2,fnorm);CHKERRQ(ierr);} 104 ierr = VecCopy(FPC,F);CHKERRQ(ierr); 105 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Preconditioner has no function"); 106 } else { 107 ierr = SNESGetSolution(snes->npc,&XPC);CHKERRQ(ierr); 108 if (XPC) { 109 ierr = SNESComputeFunction(snes->npc,XPC,F);CHKERRQ(ierr); 110 if (fnorm) {ierr = VecNorm(F,NORM_2,fnorm);CHKERRQ(ierr);} 111 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Preconditioner has no solution"); 112 } 113 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No preconditioner set"); 114 PetscFunctionReturn(0); 115 } 116