132f3f7c2SPeter Brune 232f3f7c2SPeter Brune #include <petsc-private/snesimpl.h> /*I "petscsnes.h" I*/ 332f3f7c2SPeter Brune #include <petscdmshell.h> 432f3f7c2SPeter Brune 532f3f7c2SPeter Brune 632f3f7c2SPeter Brune #undef __FUNCT__ 7*be95d8f1SBarry Smith #define __FUNCT__ "SNESApplyNPC" 832f3f7c2SPeter Brune /*@ 9*be95d8f1SBarry Smith SNESApplyNPC - Calls SNESSolve() on preconditioner for the SNES 1032f3f7c2SPeter Brune 1132f3f7c2SPeter Brune Collective on SNES 1232f3f7c2SPeter Brune 1332f3f7c2SPeter Brune Input Parameters: 1432f3f7c2SPeter Brune + snes - the SNES context 156a63999bSPeter Brune . x - input vector 166a63999bSPeter Brune - f - optional; the function evaluation on x 1732f3f7c2SPeter Brune 1832f3f7c2SPeter Brune Output Parameter: 1932f3f7c2SPeter Brune . y - function vector, as set by SNESSetFunction() 2032f3f7c2SPeter Brune 2132f3f7c2SPeter Brune Notes: 22*be95d8f1SBarry Smith SNESComputeFunction() should be called on x before SNESApplyNPC() is called, as it is 2332f3f7c2SPeter Brune with SNESComuteJacobian(). 2432f3f7c2SPeter Brune 2532f3f7c2SPeter Brune Level: developer 2632f3f7c2SPeter Brune 2732f3f7c2SPeter Brune .keywords: SNES, nonlinear, compute, function 2832f3f7c2SPeter Brune 29*be95d8f1SBarry Smith .seealso: SNESGetNPC(),SNESSetNPC(),SNESComputeFunction() 3032f3f7c2SPeter Brune @*/ 31*be95d8f1SBarry Smith PetscErrorCode SNESApplyNPC(SNES snes,Vec x,Vec f,Vec y) 3232f3f7c2SPeter Brune { 3332f3f7c2SPeter Brune PetscErrorCode ierr; 3432f3f7c2SPeter Brune 3532f3f7c2SPeter Brune PetscFunctionBegin; 3632f3f7c2SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3732f3f7c2SPeter Brune PetscValidHeaderSpecific(x,VEC_CLASSID,2); 3832f3f7c2SPeter Brune PetscValidHeaderSpecific(y,VEC_CLASSID,3); 3932f3f7c2SPeter Brune PetscCheckSameComm(snes,1,x,2); 4032f3f7c2SPeter Brune PetscCheckSameComm(snes,1,y,3); 4132f3f7c2SPeter Brune ierr = VecValidValues(x,2,PETSC_TRUE);CHKERRQ(ierr); 4232f3f7c2SPeter Brune if (snes->pc) { 4332f3f7c2SPeter Brune if (f) { 4432f3f7c2SPeter Brune ierr = SNESSetInitialFunction(snes->pc,f);CHKERRQ(ierr); 4532f3f7c2SPeter Brune } 4632f3f7c2SPeter Brune ierr = VecCopy(x,y);CHKERRQ(ierr); 4732f3f7c2SPeter Brune ierr = PetscLogEventBegin(SNES_NPCSolve,snes->pc,x,y,0);CHKERRQ(ierr); 4832f3f7c2SPeter Brune ierr = SNESSolve(snes->pc,snes->vec_rhs,y);CHKERRQ(ierr); 4932f3f7c2SPeter Brune ierr = PetscLogEventEnd(SNES_NPCSolve,snes->pc,x,y,0);CHKERRQ(ierr); 5032f3f7c2SPeter Brune ierr = VecAYPX(y,-1.0,x);CHKERRQ(ierr); 5132f3f7c2SPeter Brune PetscFunctionReturn(0); 5232f3f7c2SPeter Brune } 5332f3f7c2SPeter Brune PetscFunctionReturn(0); 5432f3f7c2SPeter Brune } 5532f3f7c2SPeter Brune 5632f3f7c2SPeter Brune #undef __FUNCT__ 57*be95d8f1SBarry Smith #define __FUNCT__ "SNESComputeFunctionDefaultNPC" 58*be95d8f1SBarry Smith PetscErrorCode SNESComputeFunctionDefaultNPC(SNES snes,Vec X,Vec F) 59*be95d8f1SBarry Smith { 6032f3f7c2SPeter Brune /* This is to be used as an argument to SNESMF -- NOT as a "function" */ 61b7281c8aSPeter Brune SNESConvergedReason reason; 6232f3f7c2SPeter Brune PetscErrorCode ierr; 63b7281c8aSPeter Brune 6432f3f7c2SPeter Brune PetscFunctionBegin; 65b7281c8aSPeter Brune if (snes->pc) { 66*be95d8f1SBarry Smith ierr = SNESApplyNPC(snes,X,NULL,F);CHKERRQ(ierr); 67b7281c8aSPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 68b7281c8aSPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 69b7281c8aSPeter Brune ierr = SNESSetFunctionDomainError(snes);CHKERRQ(ierr); 70b7281c8aSPeter Brune } 71b7281c8aSPeter Brune } else { 72b7281c8aSPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 73b7281c8aSPeter Brune } 7432f3f7c2SPeter Brune PetscFunctionReturn(0); 7532f3f7c2SPeter Brune } 76ddd40ce5SPeter Brune 77ddd40ce5SPeter Brune #undef __FUNCT__ 78*be95d8f1SBarry Smith #define __FUNCT__ "SNESGetNPCFunction" 79ddd40ce5SPeter Brune /*@ 80*be95d8f1SBarry Smith SNESGetNPCFunction - Gets the function from a preconditioner after SNESSolve() has been called. 81ddd40ce5SPeter Brune 82ddd40ce5SPeter Brune Collective on SNES 83ddd40ce5SPeter Brune 84ddd40ce5SPeter Brune Input Parameters: 85ddd40ce5SPeter Brune . snes - the SNES context 86ddd40ce5SPeter Brune 87ddd40ce5SPeter Brune Output Parameter: 88ddd40ce5SPeter Brune . F - function vector 89ddd40ce5SPeter Brune . fnorm - the norm of F 90ddd40ce5SPeter Brune 91ddd40ce5SPeter Brune Level: developer 92ddd40ce5SPeter Brune 93ddd40ce5SPeter Brune .keywords: SNES, nonlinear, function 94ddd40ce5SPeter Brune 95*be95d8f1SBarry Smith .seealso: SNESGetNPC(),SNESSetNPC(),SNESComputeFunction(),SNESApplyNPC(),SNESSolve() 96ddd40ce5SPeter Brune @*/ 97*be95d8f1SBarry Smith PetscErrorCode SNESGetNPCFunction(SNES snes,Vec F,PetscReal *fnorm) 98ddd40ce5SPeter Brune { 99ddd40ce5SPeter Brune PetscErrorCode ierr; 100ddd40ce5SPeter Brune PCSide npcside; 101ddd40ce5SPeter Brune SNESFunctionType functype; 102ddd40ce5SPeter Brune SNESNormSchedule normschedule; 103ddd40ce5SPeter Brune Vec FPC,XPC; 104ddd40ce5SPeter Brune 105ddd40ce5SPeter Brune PetscFunctionBegin; 106ddd40ce5SPeter Brune if (snes->pc) { 107*be95d8f1SBarry Smith ierr = SNESGetNPCSide(snes->pc,&npcside);CHKERRQ(ierr); 108ddd40ce5SPeter Brune ierr = SNESGetFunctionType(snes->pc,&functype);CHKERRQ(ierr); 109ddd40ce5SPeter Brune ierr = SNESGetNormSchedule(snes->pc,&normschedule);CHKERRQ(ierr); 110ddd40ce5SPeter Brune 111ddd40ce5SPeter Brune /* check if the function is valid based upon how the inner solver is preconditioned */ 112ddd40ce5SPeter Brune if (normschedule != SNES_NORM_NONE && normschedule != SNES_NORM_INITIAL_ONLY && (npcside == PC_RIGHT || functype == SNES_FUNCTION_UNPRECONDITIONED)) { 113ddd40ce5SPeter Brune ierr = SNESGetFunction(snes->pc,&FPC,NULL,NULL);CHKERRQ(ierr); 1141d3ed18cSPeter Brune if (FPC) { 115ddd40ce5SPeter Brune if (fnorm) {ierr = SNESGetFunctionNorm(snes->pc,fnorm);CHKERRQ(ierr);} 116ddd40ce5SPeter Brune ierr = VecCopy(FPC,F);CHKERRQ(ierr); 117ddd40ce5SPeter Brune } else { 118ddd40ce5SPeter Brune SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Preconditioner has no function"); 119ddd40ce5SPeter Brune } 120ddd40ce5SPeter Brune } else { 121ddd40ce5SPeter Brune ierr = SNESGetSolution(snes->pc,&XPC);CHKERRQ(ierr); 122ddd40ce5SPeter Brune if (XPC) { 123ddd40ce5SPeter Brune ierr = SNESComputeFunction(snes->pc,XPC,F);CHKERRQ(ierr); 124ddd40ce5SPeter Brune if (fnorm) {ierr = VecNorm(F,NORM_2,fnorm);CHKERRQ(ierr);} 12537703b41SBarry Smith } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Preconditioner has no solution"); 126ddd40ce5SPeter Brune } 12737703b41SBarry Smith } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No preconditioner set"); 128ddd40ce5SPeter Brune PetscFunctionReturn(0); 129ddd40ce5SPeter Brune } 130