12a4ee8f2SPeter Brune #include <petsc-private/snesimpl.h> 22a4ee8f2SPeter Brune 3*075cc632SBarry Smith /*MC 4*075cc632SBarry Smith SNESObjectiveFunction - functional form used to convey the objective function to the nonlinear solver 52a4ee8f2SPeter Brune 6*075cc632SBarry Smith Synopsis: 7*075cc632SBarry Smith #include "petscsnes.h" 8*075cc632SBarry Smith SNESObjectiveFunction(SNES snes,Vec x,PetscReal *obj,void *ctx); 92a4ee8f2SPeter Brune 102a4ee8f2SPeter Brune Input Parameters: 112a4ee8f2SPeter Brune + snes - the SNES context 122a4ee8f2SPeter Brune . X - solution 132a4ee8f2SPeter Brune . F - current function/gradient 142a4ee8f2SPeter Brune . obj - real to hold the objective value 152a4ee8f2SPeter Brune - ctx - optional user-defined objective context 162a4ee8f2SPeter Brune 17*075cc632SBarry Smith .seealso: SNESSetFunction(), SNESGetFunction(), SNESSetObjectiveFunction(), SNESGetObjectiveFunction() 18*075cc632SBarry Smith M*/ 19*075cc632SBarry Smith 20*075cc632SBarry Smith 21*075cc632SBarry Smith #undef __FUNCT__ 22*075cc632SBarry Smith #define __FUNCT__ "SNESSetObjective" 23*075cc632SBarry Smith /*@C 24*075cc632SBarry Smith SNESSetObjective - Sets the objective function minimized by the SNES methods. 25*075cc632SBarry Smith 26*075cc632SBarry Smith Logically Collective on SNES 27*075cc632SBarry Smith 28*075cc632SBarry Smith Input Parameters: 29*075cc632SBarry Smith + snes - the SNES context 30*075cc632SBarry Smith . SNESObjectiveFunction - objective evaluation routine 31*075cc632SBarry Smith - ctx - [optional] user-defined context for private data for the 32*075cc632SBarry Smith function evaluation routine (may be PETSC_NULL) 33*075cc632SBarry Smith 342a4ee8f2SPeter Brune Level: beginner 352a4ee8f2SPeter Brune 36*075cc632SBarry Smith Note: If not provided then this defaults to the two norm of the function evaluation (set with SNESSetFunction()) 37*075cc632SBarry Smith 382a4ee8f2SPeter Brune .keywords: SNES, nonlinear, set, objective 392a4ee8f2SPeter Brune 40*075cc632SBarry Smith .seealso: SNESGetObjective(), SNESComputeObjective(), SNESSetFunction(), SNESSetJacobian(), SNESObjectiveFunction 412a4ee8f2SPeter Brune @*/ 42*075cc632SBarry Smith PetscErrorCode SNESSetObjective(SNES snes,PetscErrorCode (*SNESObjectiveFunction)(SNES,Vec,PetscReal *,void*),void *ctx) 432a4ee8f2SPeter Brune { 442a4ee8f2SPeter Brune PetscErrorCode ierr; 452a4ee8f2SPeter Brune DM dm; 462a4ee8f2SPeter Brune 472a4ee8f2SPeter Brune PetscFunctionBegin; 482a4ee8f2SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 492a4ee8f2SPeter Brune ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 50*075cc632SBarry Smith ierr = DMSNESSetObjective(dm,SNESObjectiveFunction,ctx);CHKERRQ(ierr); 512a4ee8f2SPeter Brune PetscFunctionReturn(0); 522a4ee8f2SPeter Brune } 532a4ee8f2SPeter Brune 542a4ee8f2SPeter Brune #undef __FUNCT__ 552a4ee8f2SPeter Brune #define __FUNCT__ "SNESGetObjective" 562a4ee8f2SPeter Brune /*@C 572a4ee8f2SPeter Brune SNESGetObjective - Returns the objective function. 582a4ee8f2SPeter Brune 592a4ee8f2SPeter Brune Not Collective 602a4ee8f2SPeter Brune 612a4ee8f2SPeter Brune Input Parameter: 622a4ee8f2SPeter Brune . snes - the SNES context 632a4ee8f2SPeter Brune 642a4ee8f2SPeter Brune Output Parameter: 652a4ee8f2SPeter Brune + func - the function (or PETSC_NULL) 662a4ee8f2SPeter Brune - ctx - the function context (or PETSC_NULL) 672a4ee8f2SPeter Brune 682a4ee8f2SPeter Brune Level: advanced 692a4ee8f2SPeter Brune 702a4ee8f2SPeter Brune .keywords: SNES, nonlinear, get, objective 712a4ee8f2SPeter Brune 722a4ee8f2SPeter Brune .seealso: SNESSetObjective(), SNESGetSolution() 732a4ee8f2SPeter Brune @*/ 74*075cc632SBarry Smith PetscErrorCode SNESGetObjective(SNES snes,PetscErrorCode (**SNESObjectiveFunction)(SNES,Vec,PetscReal *,void*),void **ctx) 752a4ee8f2SPeter Brune { 762a4ee8f2SPeter Brune PetscErrorCode ierr; 772a4ee8f2SPeter Brune DM dm; 782a4ee8f2SPeter Brune PetscFunctionBegin; 792a4ee8f2SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 802a4ee8f2SPeter Brune ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 81*075cc632SBarry Smith ierr = DMSNESGetObjective(dm,SNESObjectiveFunction,ctx);CHKERRQ(ierr); 822a4ee8f2SPeter Brune PetscFunctionReturn(0); 832a4ee8f2SPeter Brune } 842a4ee8f2SPeter Brune 852a4ee8f2SPeter Brune #undef __FUNCT__ 862a4ee8f2SPeter Brune #define __FUNCT__ "SNESComputeObjective" 872a4ee8f2SPeter Brune /*@C 882a4ee8f2SPeter Brune SNESComputeObjective - Computes the objective. 892a4ee8f2SPeter Brune 902a4ee8f2SPeter Brune Collective on SNES 912a4ee8f2SPeter Brune 922a4ee8f2SPeter Brune Input Parameter: 932a4ee8f2SPeter Brune + snes - the SNES context 942a4ee8f2SPeter Brune - X - the state vector 952a4ee8f2SPeter Brune 962a4ee8f2SPeter Brune Output Parameter: 972a4ee8f2SPeter Brune . ob - the objective value 982a4ee8f2SPeter Brune 992a4ee8f2SPeter Brune Level: advanced 1002a4ee8f2SPeter Brune 1012a4ee8f2SPeter Brune .keywords: SNES, nonlinear, compute, objective 1022a4ee8f2SPeter Brune 1032a4ee8f2SPeter Brune .seealso: SNESSetObjective(), SNESGetSolution() 1042a4ee8f2SPeter Brune @*/ 1052a4ee8f2SPeter Brune PetscErrorCode SNESComputeObjective(SNES snes,Vec X,PetscReal *ob) 1062a4ee8f2SPeter Brune { 1072a4ee8f2SPeter Brune PetscErrorCode ierr; 1082a4ee8f2SPeter Brune DM dm; 109942e3340SBarry Smith DMSNES sdm; 1102a4ee8f2SPeter Brune PetscFunctionBegin; 1112a4ee8f2SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1122a4ee8f2SPeter Brune PetscValidHeaderSpecific(X,VEC_CLASSID,2); 1132a4ee8f2SPeter Brune PetscValidPointer(ob,3); 1142a4ee8f2SPeter Brune ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 115942e3340SBarry Smith ierr = DMGetDMSNES(dm,&sdm);CHKERRQ(ierr); 11622c6f798SBarry Smith if (sdm->ops->computeobjective) { 11722c6f798SBarry Smith ierr = (sdm->ops->computeobjective)(snes,X,ob,sdm->objectivectx);CHKERRQ(ierr); 11887d70a26SPeter Brune } else { 11974d836f3SPeter Brune SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetObjective() before SNESComputeObjective()."); 12087d70a26SPeter Brune } 1212a4ee8f2SPeter Brune PetscFunctionReturn(0); 1222a4ee8f2SPeter Brune } 12397584545SPeter Brune 12497584545SPeter Brune 12597584545SPeter Brune #undef __FUNCT__ 12697584545SPeter Brune #define __FUNCT__ "SNESDefaultObjectiveComputeFunctionFD" 12797584545SPeter Brune PetscErrorCode SNESDefaultObjectiveComputeFunctionFD(SNES snes,Vec X,Vec F,void *ctx) { 12897584545SPeter Brune /* Quadratically interpolates the change in the objective based upon a change in a particular direction */ 12997584545SPeter Brune 13097584545SPeter Brune Vec Xh; 13197584545SPeter Brune PetscErrorCode ierr; 13297584545SPeter Brune PetscInt i,N,start,end; 13397584545SPeter Brune PetscReal ob,ob1,ob2,ob3,fob,dx,eps=1e-6; 13497584545SPeter Brune PetscScalar fv,xv; 13597584545SPeter Brune 13697584545SPeter Brune PetscFunctionBegin; 13797584545SPeter Brune ierr = VecDuplicate(X,&Xh);CHKERRQ(ierr); 13897584545SPeter Brune ierr = PetscOptionsReal("-snes_fd_function_eps","Tolerance for nonzero entries in fd function","None",eps,&eps,PETSC_NULL);CHKERRQ(ierr); 13997584545SPeter Brune ierr = VecSet(F,0.);CHKERRQ(ierr); 14097584545SPeter Brune 14197584545SPeter Brune ierr = VecNorm(X,NORM_2,&fob);CHKERRQ(ierr); 14297584545SPeter Brune 14397584545SPeter Brune ierr = VecGetSize(X,&N);CHKERRQ(ierr); 14497584545SPeter Brune ierr = VecGetOwnershipRange(X,&start,&end);CHKERRQ(ierr); 14597584545SPeter Brune ierr = SNESComputeObjective(snes,X,&ob);CHKERRQ(ierr); 14697584545SPeter Brune 14797584545SPeter Brune if (fob > 0.) { 14897584545SPeter Brune dx =1e-6*fob; 14997584545SPeter Brune } else { 15097584545SPeter Brune dx = 1e-6; 15197584545SPeter Brune } 15297584545SPeter Brune 15397584545SPeter Brune for (i=0; i<N; i++) { 15497584545SPeter Brune /* compute the 1st value */ 15597584545SPeter Brune ierr = VecCopy(X,Xh);CHKERRQ(ierr); 15697584545SPeter Brune if (i>= start && i<end) { 15797584545SPeter Brune xv = dx; 15897584545SPeter Brune ierr = VecSetValues(Xh,1,&i,&xv,ADD_VALUES);CHKERRQ(ierr); 15997584545SPeter Brune } 16097584545SPeter Brune ierr = VecAssemblyBegin(Xh);CHKERRQ(ierr); 16197584545SPeter Brune ierr = VecAssemblyEnd(Xh);CHKERRQ(ierr); 16297584545SPeter Brune ierr = SNESComputeObjective(snes,Xh,&ob1);CHKERRQ(ierr); 16397584545SPeter Brune 16497584545SPeter Brune /* compute the 2nd value */ 16597584545SPeter Brune ierr = VecCopy(X,Xh);CHKERRQ(ierr); 16697584545SPeter Brune if (i>= start && i<end) { 16797584545SPeter Brune xv = 2.*dx; 16897584545SPeter Brune ierr = VecSetValues(Xh,1,&i,&xv,ADD_VALUES);CHKERRQ(ierr); 16997584545SPeter Brune } 17097584545SPeter Brune ierr = VecAssemblyBegin(Xh);CHKERRQ(ierr); 17197584545SPeter Brune ierr = VecAssemblyEnd(Xh);CHKERRQ(ierr); 17297584545SPeter Brune ierr = SNESComputeObjective(snes,Xh,&ob2);CHKERRQ(ierr); 17397584545SPeter Brune 17497584545SPeter Brune /* compute the 3rd value */ 17597584545SPeter Brune ierr = VecCopy(X,Xh);CHKERRQ(ierr); 17697584545SPeter Brune if (i>= start && i<end) { 17797584545SPeter Brune xv = -dx; 17897584545SPeter Brune ierr = VecSetValues(Xh,1,&i,&xv,ADD_VALUES);CHKERRQ(ierr); 17997584545SPeter Brune } 18097584545SPeter Brune ierr = VecAssemblyBegin(Xh);CHKERRQ(ierr); 18197584545SPeter Brune ierr = VecAssemblyEnd(Xh);CHKERRQ(ierr); 18297584545SPeter Brune ierr = SNESComputeObjective(snes,Xh,&ob3);CHKERRQ(ierr); 18397584545SPeter Brune 18497584545SPeter Brune if (i >= start && i<end) { 18597584545SPeter Brune /* set this entry to be the gradient of the objective */ 18697584545SPeter Brune fv = (-ob2 + 6.*ob1 - 3.*ob -2.*ob3) / (6.*dx); 18797584545SPeter Brune if (PetscAbsScalar(fv) > eps) { 18897584545SPeter Brune ierr = VecSetValues(F,1,&i,&fv,INSERT_VALUES);CHKERRQ(ierr); 18997584545SPeter Brune } else { 19097584545SPeter Brune fv = 0.; 19197584545SPeter Brune ierr = VecSetValues(F,1,&i,&fv,INSERT_VALUES);CHKERRQ(ierr); 19297584545SPeter Brune } 19397584545SPeter Brune } 19497584545SPeter Brune } 19597584545SPeter Brune 19697584545SPeter Brune ierr = VecDestroy(&Xh);CHKERRQ(ierr); 19797584545SPeter Brune 19897584545SPeter Brune ierr = VecAssemblyBegin(F);CHKERRQ(ierr); 19997584545SPeter Brune ierr = VecAssemblyEnd(F);CHKERRQ(ierr); 20097584545SPeter Brune PetscFunctionReturn(0); 20197584545SPeter Brune } 202