12a4ee8f2SPeter Brune #include <petsc-private/snesimpl.h> 22a4ee8f2SPeter Brune 3075cc632SBarry Smith /*MC 4075cc632SBarry Smith SNESObjectiveFunction - functional form used to convey the objective function to the nonlinear solver 52a4ee8f2SPeter Brune 6075cc632SBarry Smith Synopsis: 7075cc632SBarry Smith #include "petscsnes.h" 8075cc632SBarry 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*878cb397SSatish Balay Level: advanced 18*878cb397SSatish Balay 19075cc632SBarry Smith .seealso: SNESSetFunction(), SNESGetFunction(), SNESSetObjectiveFunction(), SNESGetObjectiveFunction() 20075cc632SBarry Smith M*/ 21075cc632SBarry Smith 22075cc632SBarry Smith 23075cc632SBarry Smith #undef __FUNCT__ 24075cc632SBarry Smith #define __FUNCT__ "SNESSetObjective" 25075cc632SBarry Smith /*@C 26075cc632SBarry Smith SNESSetObjective - Sets the objective function minimized by the SNES methods. 27075cc632SBarry Smith 28075cc632SBarry Smith Logically Collective on SNES 29075cc632SBarry Smith 30075cc632SBarry Smith Input Parameters: 31075cc632SBarry Smith + snes - the SNES context 32075cc632SBarry Smith . SNESObjectiveFunction - objective evaluation routine 33075cc632SBarry Smith - ctx - [optional] user-defined context for private data for the 340298fd71SBarry Smith function evaluation routine (may be NULL) 35075cc632SBarry Smith 362a4ee8f2SPeter Brune Level: beginner 372a4ee8f2SPeter Brune 38075cc632SBarry Smith Note: If not provided then this defaults to the two norm of the function evaluation (set with SNESSetFunction()) 39075cc632SBarry Smith 402a4ee8f2SPeter Brune .keywords: SNES, nonlinear, set, objective 412a4ee8f2SPeter Brune 42075cc632SBarry Smith .seealso: SNESGetObjective(), SNESComputeObjective(), SNESSetFunction(), SNESSetJacobian(), SNESObjectiveFunction 432a4ee8f2SPeter Brune @*/ 44075cc632SBarry Smith PetscErrorCode SNESSetObjective(SNES snes,PetscErrorCode (*SNESObjectiveFunction)(SNES,Vec,PetscReal*,void*),void *ctx) 452a4ee8f2SPeter Brune { 462a4ee8f2SPeter Brune PetscErrorCode ierr; 472a4ee8f2SPeter Brune DM dm; 482a4ee8f2SPeter Brune 492a4ee8f2SPeter Brune PetscFunctionBegin; 502a4ee8f2SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 512a4ee8f2SPeter Brune ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 52075cc632SBarry Smith ierr = DMSNESSetObjective(dm,SNESObjectiveFunction,ctx);CHKERRQ(ierr); 532a4ee8f2SPeter Brune PetscFunctionReturn(0); 542a4ee8f2SPeter Brune } 552a4ee8f2SPeter Brune 562a4ee8f2SPeter Brune #undef __FUNCT__ 572a4ee8f2SPeter Brune #define __FUNCT__ "SNESGetObjective" 582a4ee8f2SPeter Brune /*@C 592a4ee8f2SPeter Brune SNESGetObjective - Returns the objective function. 602a4ee8f2SPeter Brune 612a4ee8f2SPeter Brune Not Collective 622a4ee8f2SPeter Brune 632a4ee8f2SPeter Brune Input Parameter: 642a4ee8f2SPeter Brune . snes - the SNES context 652a4ee8f2SPeter Brune 662a4ee8f2SPeter Brune Output Parameter: 670298fd71SBarry Smith + func - the function (or NULL) 680298fd71SBarry Smith - ctx - the function context (or NULL) 692a4ee8f2SPeter Brune 702a4ee8f2SPeter Brune Level: advanced 712a4ee8f2SPeter Brune 722a4ee8f2SPeter Brune .keywords: SNES, nonlinear, get, objective 732a4ee8f2SPeter Brune 742a4ee8f2SPeter Brune .seealso: SNESSetObjective(), SNESGetSolution() 752a4ee8f2SPeter Brune @*/ 76075cc632SBarry Smith PetscErrorCode SNESGetObjective(SNES snes,PetscErrorCode (**SNESObjectiveFunction)(SNES,Vec,PetscReal*,void*),void **ctx) 772a4ee8f2SPeter Brune { 782a4ee8f2SPeter Brune PetscErrorCode ierr; 792a4ee8f2SPeter Brune DM dm; 805fd66863SKarl Rupp 812a4ee8f2SPeter Brune PetscFunctionBegin; 822a4ee8f2SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 832a4ee8f2SPeter Brune ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 84075cc632SBarry Smith ierr = DMSNESGetObjective(dm,SNESObjectiveFunction,ctx);CHKERRQ(ierr); 852a4ee8f2SPeter Brune PetscFunctionReturn(0); 862a4ee8f2SPeter Brune } 872a4ee8f2SPeter Brune 882a4ee8f2SPeter Brune #undef __FUNCT__ 892a4ee8f2SPeter Brune #define __FUNCT__ "SNESComputeObjective" 902a4ee8f2SPeter Brune /*@C 912a4ee8f2SPeter Brune SNESComputeObjective - Computes the objective. 922a4ee8f2SPeter Brune 932a4ee8f2SPeter Brune Collective on SNES 942a4ee8f2SPeter Brune 952a4ee8f2SPeter Brune Input Parameter: 962a4ee8f2SPeter Brune + snes - the SNES context 972a4ee8f2SPeter Brune - X - the state vector 982a4ee8f2SPeter Brune 992a4ee8f2SPeter Brune Output Parameter: 1002a4ee8f2SPeter Brune . ob - the objective value 1012a4ee8f2SPeter Brune 1022a4ee8f2SPeter Brune Level: advanced 1032a4ee8f2SPeter Brune 1042a4ee8f2SPeter Brune .keywords: SNES, nonlinear, compute, objective 1052a4ee8f2SPeter Brune 1062a4ee8f2SPeter Brune .seealso: SNESSetObjective(), SNESGetSolution() 1072a4ee8f2SPeter Brune @*/ 1082a4ee8f2SPeter Brune PetscErrorCode SNESComputeObjective(SNES snes,Vec X,PetscReal *ob) 1092a4ee8f2SPeter Brune { 1102a4ee8f2SPeter Brune PetscErrorCode ierr; 1112a4ee8f2SPeter Brune DM dm; 112942e3340SBarry Smith DMSNES sdm; 113f23aa3ddSBarry Smith 1142a4ee8f2SPeter Brune PetscFunctionBegin; 1152a4ee8f2SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1162a4ee8f2SPeter Brune PetscValidHeaderSpecific(X,VEC_CLASSID,2); 1172a4ee8f2SPeter Brune PetscValidPointer(ob,3); 1182a4ee8f2SPeter Brune ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 119942e3340SBarry Smith ierr = DMGetDMSNES(dm,&sdm);CHKERRQ(ierr); 12022c6f798SBarry Smith if (sdm->ops->computeobjective) { 12122c6f798SBarry Smith ierr = (sdm->ops->computeobjective)(snes,X,ob,sdm->objectivectx);CHKERRQ(ierr); 122ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetObjective() before SNESComputeObjective()."); 1232a4ee8f2SPeter Brune PetscFunctionReturn(0); 1242a4ee8f2SPeter Brune } 12597584545SPeter Brune 12697584545SPeter Brune 12797584545SPeter Brune #undef __FUNCT__ 1288d359177SBarry Smith #define __FUNCT__ "SNESObjectiveComputeFunctionDefaultFD" 1298d359177SBarry Smith PetscErrorCode SNESObjectiveComputeFunctionDefaultFD(SNES snes,Vec X,Vec F,void *ctx) 1300adebc6cSBarry Smith { 13197584545SPeter Brune /* Quadratically interpolates the change in the objective based upon a change in a particular direction */ 13297584545SPeter Brune 13397584545SPeter Brune Vec Xh; 13497584545SPeter Brune PetscErrorCode ierr; 13597584545SPeter Brune PetscInt i,N,start,end; 13697584545SPeter Brune PetscReal ob,ob1,ob2,ob3,fob,dx,eps=1e-6; 13797584545SPeter Brune PetscScalar fv,xv; 13897584545SPeter Brune 13997584545SPeter Brune PetscFunctionBegin; 14097584545SPeter Brune ierr = VecDuplicate(X,&Xh);CHKERRQ(ierr); 1410298fd71SBarry Smith ierr = PetscOptionsReal("-snes_fd_function_eps","Tolerance for nonzero entries in fd function","None",eps,&eps,NULL);CHKERRQ(ierr); 14297584545SPeter Brune ierr = VecSet(F,0.);CHKERRQ(ierr); 14397584545SPeter Brune 14497584545SPeter Brune ierr = VecNorm(X,NORM_2,&fob);CHKERRQ(ierr); 14597584545SPeter Brune 14697584545SPeter Brune ierr = VecGetSize(X,&N);CHKERRQ(ierr); 14797584545SPeter Brune ierr = VecGetOwnershipRange(X,&start,&end);CHKERRQ(ierr); 14897584545SPeter Brune ierr = SNESComputeObjective(snes,X,&ob);CHKERRQ(ierr); 14997584545SPeter Brune 150f5af7f23SKarl Rupp if (fob > 0.) dx =1e-6*fob; 151f5af7f23SKarl Rupp else dx = 1e-6; 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