12a4ee8f2SPeter Brune #include <petsc-private/snesimpl.h> 22a4ee8f2SPeter Brune 32a4ee8f2SPeter Brune #undef __FUNCT__ 42a4ee8f2SPeter Brune #define __FUNCT__ "SNESSetObjective" 52a4ee8f2SPeter Brune /*@C 62a4ee8f2SPeter Brune SNESSetObjective - Sets the objective function minimized by 72a4ee8f2SPeter Brune the SNES methods. 82a4ee8f2SPeter Brune 92a4ee8f2SPeter Brune Logically Collective on SNES 102a4ee8f2SPeter Brune 112a4ee8f2SPeter Brune Input Parameters: 122a4ee8f2SPeter Brune + snes - the SNES context 132a4ee8f2SPeter Brune . func - objective evaluation routine 142a4ee8f2SPeter Brune - ctx - [optional] user-defined context for private data for the 152a4ee8f2SPeter Brune function evaluation routine (may be PETSC_NULL) 162a4ee8f2SPeter Brune 172a4ee8f2SPeter Brune Calling sequence of func: 182a4ee8f2SPeter Brune $ func (SNES snes,Vec x,PetscReal *obj,void *ctx); 192a4ee8f2SPeter Brune 202a4ee8f2SPeter Brune + snes - the SNES context 212a4ee8f2SPeter Brune . X - solution 222a4ee8f2SPeter Brune . F - current function/gradient 232a4ee8f2SPeter Brune . obj - real to hold the objective value 242a4ee8f2SPeter Brune - ctx - optional user-defined objective context 252a4ee8f2SPeter Brune 262a4ee8f2SPeter Brune Level: beginner 272a4ee8f2SPeter Brune 282a4ee8f2SPeter Brune .keywords: SNES, nonlinear, set, objective 292a4ee8f2SPeter Brune 302a4ee8f2SPeter Brune .seealso: SNESGetObjective(), SNESComputeObjective(), SNESSetFunction(), SNESSetJacobian() 312a4ee8f2SPeter Brune @*/ 322a4ee8f2SPeter Brune PetscErrorCode SNESSetObjective(SNES snes,SNESObjective func,void *ctx) 332a4ee8f2SPeter Brune { 342a4ee8f2SPeter Brune PetscErrorCode ierr; 352a4ee8f2SPeter Brune DM dm; 362a4ee8f2SPeter Brune 372a4ee8f2SPeter Brune PetscFunctionBegin; 382a4ee8f2SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 392a4ee8f2SPeter Brune ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 402a4ee8f2SPeter Brune ierr = DMSNESSetObjective(dm,func,ctx);CHKERRQ(ierr); 412a4ee8f2SPeter Brune PetscFunctionReturn(0); 422a4ee8f2SPeter Brune } 432a4ee8f2SPeter Brune 442a4ee8f2SPeter Brune #undef __FUNCT__ 452a4ee8f2SPeter Brune #define __FUNCT__ "SNESGetObjective" 462a4ee8f2SPeter Brune /*@C 472a4ee8f2SPeter Brune SNESGetObjective - Returns the objective function. 482a4ee8f2SPeter Brune 492a4ee8f2SPeter Brune Not Collective 502a4ee8f2SPeter Brune 512a4ee8f2SPeter Brune Input Parameter: 522a4ee8f2SPeter Brune . snes - the SNES context 532a4ee8f2SPeter Brune 542a4ee8f2SPeter Brune Output Parameter: 552a4ee8f2SPeter Brune + func - the function (or PETSC_NULL) 562a4ee8f2SPeter Brune - ctx - the function context (or PETSC_NULL) 572a4ee8f2SPeter Brune 582a4ee8f2SPeter Brune Level: advanced 592a4ee8f2SPeter Brune 602a4ee8f2SPeter Brune .keywords: SNES, nonlinear, get, objective 612a4ee8f2SPeter Brune 622a4ee8f2SPeter Brune .seealso: SNESSetObjective(), SNESGetSolution() 632a4ee8f2SPeter Brune @*/ 642a4ee8f2SPeter Brune PetscErrorCode SNESGetObjective(SNES snes,SNESObjective *func,void **ctx) 652a4ee8f2SPeter Brune { 662a4ee8f2SPeter Brune PetscErrorCode ierr; 672a4ee8f2SPeter Brune DM dm; 682a4ee8f2SPeter Brune PetscFunctionBegin; 692a4ee8f2SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 702a4ee8f2SPeter Brune ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 712a4ee8f2SPeter Brune ierr = DMSNESGetObjective(dm,func,ctx);CHKERRQ(ierr); 722a4ee8f2SPeter Brune PetscFunctionReturn(0); 732a4ee8f2SPeter Brune } 742a4ee8f2SPeter Brune 752a4ee8f2SPeter Brune #undef __FUNCT__ 762a4ee8f2SPeter Brune #define __FUNCT__ "SNESComputeObjective" 772a4ee8f2SPeter Brune /*@C 782a4ee8f2SPeter Brune SNESComputeObjective - Computes the objective. 792a4ee8f2SPeter Brune 802a4ee8f2SPeter Brune Collective on SNES 812a4ee8f2SPeter Brune 822a4ee8f2SPeter Brune Input Parameter: 832a4ee8f2SPeter Brune + snes - the SNES context 842a4ee8f2SPeter Brune - X - the state vector 852a4ee8f2SPeter Brune 862a4ee8f2SPeter Brune Output Parameter: 872a4ee8f2SPeter Brune . ob - the objective value 882a4ee8f2SPeter Brune 892a4ee8f2SPeter Brune Level: advanced 902a4ee8f2SPeter Brune 912a4ee8f2SPeter Brune .keywords: SNES, nonlinear, compute, objective 922a4ee8f2SPeter Brune 932a4ee8f2SPeter Brune .seealso: SNESSetObjective(), SNESGetSolution() 942a4ee8f2SPeter Brune @*/ 952a4ee8f2SPeter Brune PetscErrorCode SNESComputeObjective(SNES snes,Vec X,PetscReal *ob) 962a4ee8f2SPeter Brune { 972a4ee8f2SPeter Brune PetscErrorCode ierr; 982a4ee8f2SPeter Brune DM dm; 992a4ee8f2SPeter Brune SNESDM sdm; 1002a4ee8f2SPeter Brune PetscFunctionBegin; 1012a4ee8f2SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1022a4ee8f2SPeter Brune PetscValidHeaderSpecific(X,VEC_CLASSID,2); 1032a4ee8f2SPeter Brune PetscValidPointer(ob,3); 1042a4ee8f2SPeter Brune ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 1052a4ee8f2SPeter Brune ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr); 1062a4ee8f2SPeter Brune if (sdm->computeobjective) { 1072a4ee8f2SPeter Brune ierr = (sdm->computeobjective)(snes,X,ob,sdm->objectivectx);CHKERRQ(ierr); 1082a4ee8f2SPeter Brune } else { 1092a4ee8f2SPeter Brune SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetObjective() before SNESComputeObjective()."); 1102a4ee8f2SPeter Brune } 1112a4ee8f2SPeter Brune PetscFunctionReturn(0); 1122a4ee8f2SPeter Brune } 113*97584545SPeter Brune 114*97584545SPeter Brune 115*97584545SPeter Brune #undef __FUNCT__ 116*97584545SPeter Brune #define __FUNCT__ "SNESDefaultObjectiveComputeFunctionFD" 117*97584545SPeter Brune PetscErrorCode SNESDefaultObjectiveComputeFunctionFD(SNES snes,Vec X,Vec F,void *ctx) { 118*97584545SPeter Brune /* Quadratically interpolates the change in the objective based upon a change in a particular direction */ 119*97584545SPeter Brune 120*97584545SPeter Brune Vec Xh; 121*97584545SPeter Brune PetscErrorCode ierr; 122*97584545SPeter Brune PetscInt i,N,start,end; 123*97584545SPeter Brune PetscReal ob,ob1,ob2,ob3,fob,dx,eps=1e-6; 124*97584545SPeter Brune PetscScalar fv,xv; 125*97584545SPeter Brune 126*97584545SPeter Brune PetscFunctionBegin; 127*97584545SPeter Brune ierr = VecDuplicate(X,&Xh);CHKERRQ(ierr); 128*97584545SPeter Brune ierr = PetscOptionsReal("-snes_fd_function_eps","Tolerance for nonzero entries in fd function","None",eps,&eps,PETSC_NULL);CHKERRQ(ierr); 129*97584545SPeter Brune ierr = VecSet(F,0.);CHKERRQ(ierr); 130*97584545SPeter Brune 131*97584545SPeter Brune ierr = VecNorm(X,NORM_2,&fob);CHKERRQ(ierr); 132*97584545SPeter Brune 133*97584545SPeter Brune ierr = VecGetSize(X,&N);CHKERRQ(ierr); 134*97584545SPeter Brune ierr = VecGetOwnershipRange(X,&start,&end);CHKERRQ(ierr); 135*97584545SPeter Brune ierr = SNESComputeObjective(snes,X,&ob);CHKERRQ(ierr); 136*97584545SPeter Brune 137*97584545SPeter Brune if (fob > 0.) { 138*97584545SPeter Brune dx =1e-6*fob; 139*97584545SPeter Brune } else { 140*97584545SPeter Brune dx = 1e-6; 141*97584545SPeter Brune } 142*97584545SPeter Brune 143*97584545SPeter Brune for (i=0; i<N; i++) { 144*97584545SPeter Brune /* compute the 1st value */ 145*97584545SPeter Brune ierr = VecCopy(X,Xh);CHKERRQ(ierr); 146*97584545SPeter Brune if (i>= start && i<end) { 147*97584545SPeter Brune xv = dx; 148*97584545SPeter Brune ierr = VecSetValues(Xh,1,&i,&xv,ADD_VALUES);CHKERRQ(ierr); 149*97584545SPeter Brune } 150*97584545SPeter Brune ierr = VecAssemblyBegin(Xh);CHKERRQ(ierr); 151*97584545SPeter Brune ierr = VecAssemblyEnd(Xh);CHKERRQ(ierr); 152*97584545SPeter Brune ierr = SNESComputeObjective(snes,Xh,&ob1);CHKERRQ(ierr); 153*97584545SPeter Brune 154*97584545SPeter Brune /* compute the 2nd value */ 155*97584545SPeter Brune ierr = VecCopy(X,Xh);CHKERRQ(ierr); 156*97584545SPeter Brune if (i>= start && i<end) { 157*97584545SPeter Brune xv = 2.*dx; 158*97584545SPeter Brune ierr = VecSetValues(Xh,1,&i,&xv,ADD_VALUES);CHKERRQ(ierr); 159*97584545SPeter Brune } 160*97584545SPeter Brune ierr = VecAssemblyBegin(Xh);CHKERRQ(ierr); 161*97584545SPeter Brune ierr = VecAssemblyEnd(Xh);CHKERRQ(ierr); 162*97584545SPeter Brune ierr = SNESComputeObjective(snes,Xh,&ob2);CHKERRQ(ierr); 163*97584545SPeter Brune 164*97584545SPeter Brune /* compute the 3rd value */ 165*97584545SPeter Brune ierr = VecCopy(X,Xh);CHKERRQ(ierr); 166*97584545SPeter Brune if (i>= start && i<end) { 167*97584545SPeter Brune xv = -dx; 168*97584545SPeter Brune ierr = VecSetValues(Xh,1,&i,&xv,ADD_VALUES);CHKERRQ(ierr); 169*97584545SPeter Brune } 170*97584545SPeter Brune ierr = VecAssemblyBegin(Xh);CHKERRQ(ierr); 171*97584545SPeter Brune ierr = VecAssemblyEnd(Xh);CHKERRQ(ierr); 172*97584545SPeter Brune ierr = SNESComputeObjective(snes,Xh,&ob3);CHKERRQ(ierr); 173*97584545SPeter Brune 174*97584545SPeter Brune if (i >= start && i<end) { 175*97584545SPeter Brune /* set this entry to be the gradient of the objective */ 176*97584545SPeter Brune fv = (-ob2 + 6.*ob1 - 3.*ob -2.*ob3) / (6.*dx); 177*97584545SPeter Brune if (PetscAbsScalar(fv) > eps) { 178*97584545SPeter Brune ierr = VecSetValues(F,1,&i,&fv,INSERT_VALUES);CHKERRQ(ierr); 179*97584545SPeter Brune } else { 180*97584545SPeter Brune fv = 0.; 181*97584545SPeter Brune ierr = VecSetValues(F,1,&i,&fv,INSERT_VALUES);CHKERRQ(ierr); 182*97584545SPeter Brune } 183*97584545SPeter Brune } 184*97584545SPeter Brune } 185*97584545SPeter Brune 186*97584545SPeter Brune ierr = VecDestroy(&Xh);CHKERRQ(ierr); 187*97584545SPeter Brune 188*97584545SPeter Brune ierr = VecAssemblyBegin(F);CHKERRQ(ierr); 189*97584545SPeter Brune ierr = VecAssemblyEnd(F);CHKERRQ(ierr); 190*97584545SPeter Brune PetscFunctionReturn(0); 191*97584545SPeter Brune } 192