1 #include <petsctao.h> /*I "petsctao.h" I*/ 2 #include <petsc/private/taoimpl.h> 3 #include <petscsnes.h> 4 #include <petscdmshell.h> 5 6 /* 7 For finited difference computations of the Hessian, we use PETSc's SNESComputeJacobianDefault 8 */ 9 static PetscErrorCode Fsnes(SNES snes,Vec X,Vec G,void* ctx) 10 { 11 PetscErrorCode ierr; 12 Tao tao = (Tao)ctx; 13 14 PetscFunctionBegin; 15 PetscValidHeaderSpecific(tao,TAO_CLASSID,4); 16 ierr = TaoComputeGradient(tao,X,G);CHKERRQ(ierr); 17 PetscFunctionReturn(0); 18 } 19 20 /*@C 21 TaoDefaultComputeGradient - computes the gradient using finite differences. 22 23 Collective on Tao 24 25 Input Parameters: 26 + tao - the Tao context 27 . X - compute gradient at this point 28 - dummy - not used 29 30 Output Parameter: 31 . G - Gradient Vector 32 33 Options Database Key: 34 + -tao_fd_gradient - activates TaoDefaultComputeGradient() 35 - -tao_fd_delta <delta> - change in X used to calculate finite differences 36 37 Level: advanced 38 39 Notes: 40 This routine is slow and expensive, and is not currently optimized 41 to take advantage of sparsity in the problem. Although 42 TaoDefaultComputeGradient is not recommended for general use 43 in large-scale applications, It can be useful in checking the 44 correctness of a user-provided gradient. Use the tao method TAOTEST 45 to get an indication of whether your gradient is correct. 46 This finite difference gradient evaluation can be set using the routine TaoSetGradientRoutine() or by using the command line option -tao_fd_gradient 47 48 .seealso: TaoSetGradientRoutine() 49 @*/ 50 PetscErrorCode TaoDefaultComputeGradient(Tao tao,Vec Xin,Vec G,void *dummy) 51 { 52 Vec X; 53 PetscScalar *g; 54 PetscReal f, f2; 55 PetscErrorCode ierr; 56 PetscInt low,high,N,i; 57 PetscBool flg; 58 PetscReal h=.5*PETSC_SQRT_MACHINE_EPSILON; 59 60 PetscFunctionBegin; 61 ierr = PetscOptionsGetReal(((PetscObject)tao)->options,((PetscObject)tao)->prefix,"-tao_fd_delta",&h,&flg);CHKERRQ(ierr); 62 ierr = VecDuplicate(Xin,&X);CHKERRQ(ierr); 63 ierr = VecCopy(Xin,X);CHKERRQ(ierr); 64 ierr = VecGetSize(X,&N);CHKERRQ(ierr); 65 ierr = VecGetOwnershipRange(X,&low,&high);CHKERRQ(ierr); 66 ierr = VecSetOption(X,VEC_IGNORE_OFF_PROC_ENTRIES,PETSC_TRUE);CHKERRQ(ierr); 67 ierr = VecGetArray(G,&g);CHKERRQ(ierr); 68 for (i=0;i<N;i++) { 69 ierr = VecSetValue(X,i,-h,ADD_VALUES);CHKERRQ(ierr); 70 ierr = VecAssemblyBegin(X);CHKERRQ(ierr); 71 ierr = VecAssemblyEnd(X);CHKERRQ(ierr); 72 ierr = TaoComputeObjective(tao,X,&f);CHKERRQ(ierr); 73 ierr = VecSetValue(X,i,2.0*h,ADD_VALUES);CHKERRQ(ierr); 74 ierr = VecAssemblyBegin(X);CHKERRQ(ierr); 75 ierr = VecAssemblyEnd(X);CHKERRQ(ierr); 76 ierr = TaoComputeObjective(tao,X,&f2);CHKERRQ(ierr); 77 ierr = VecSetValue(X,i,-h,ADD_VALUES);CHKERRQ(ierr); 78 ierr = VecAssemblyBegin(X);CHKERRQ(ierr); 79 ierr = VecAssemblyEnd(X);CHKERRQ(ierr); 80 if (i>=low && i<high) { 81 g[i-low]=(f2-f)/(2.0*h); 82 } 83 } 84 ierr = VecRestoreArray(G,&g);CHKERRQ(ierr); 85 ierr = VecDestroy(&X);CHKERRQ(ierr); 86 PetscFunctionReturn(0); 87 } 88 89 /*@C 90 TaoDefaultComputeHessian - Computes the Hessian using finite differences. 91 92 Collective on Tao 93 94 Input Parameters: 95 + tao - the Tao context 96 . V - compute Hessian at this point 97 - dummy - not used 98 99 Output Parameters: 100 + H - Hessian matrix (not altered in this routine) 101 - B - newly computed Hessian matrix to use with preconditioner (generally the same as H) 102 103 Options Database Key: 104 . -tao_fd_hessian - activates TaoDefaultComputeHessian() 105 106 Level: advanced 107 108 Notes: 109 This routine is slow and expensive, and is not currently optimized 110 to take advantage of sparsity in the problem. Although 111 TaoDefaultComputeHessian() is not recommended for general use 112 in large-scale applications, It can be useful in checking the 113 correctness of a user-provided Hessian. 114 115 .seealso: TaoSetHessianRoutine(), TaoDefaultComputeHessianColor(), SNESComputeJacobianDefault(), TaoSetGradientRoutine(), TaoDefaultComputeGradient() 116 @*/ 117 PetscErrorCode TaoDefaultComputeHessian(Tao tao,Vec V,Mat H,Mat B,void *dummy) 118 { 119 PetscErrorCode ierr; 120 SNES snes; 121 DM dm; 122 123 PetscFunctionBegin; 124 ierr = PetscInfo(tao,"TAO Using finite differences w/o coloring to compute Hessian matrix\n");CHKERRQ(ierr); 125 ierr = SNESCreate(PetscObjectComm((PetscObject)H),&snes);CHKERRQ(ierr); 126 ierr = SNESSetFunction(snes,NULL,Fsnes,tao);CHKERRQ(ierr); 127 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 128 ierr = DMShellSetGlobalVector(dm,V);CHKERRQ(ierr); 129 ierr = SNESSetUp(snes);CHKERRQ(ierr); 130 if (H) { 131 PetscInt n,N; 132 133 ierr = VecGetSize(V,&N);CHKERRQ(ierr); 134 ierr = VecGetLocalSize(V,&n);CHKERRQ(ierr); 135 ierr = MatSetSizes(H,n,n,N,N);CHKERRQ(ierr); 136 ierr = MatSetUp(H);CHKERRQ(ierr); 137 } 138 if (B && B != H) { 139 PetscInt n,N; 140 141 ierr = VecGetSize(V,&N);CHKERRQ(ierr); 142 ierr = VecGetLocalSize(V,&n);CHKERRQ(ierr); 143 ierr = MatSetSizes(B,n,n,N,N);CHKERRQ(ierr); 144 ierr = MatSetUp(B);CHKERRQ(ierr); 145 } 146 ierr = SNESComputeJacobianDefault(snes,V,H,B,NULL);CHKERRQ(ierr); 147 ierr = SNESDestroy(&snes);CHKERRQ(ierr); 148 PetscFunctionReturn(0); 149 } 150 151 /*@C 152 TaoDefaultComputeHessianColor - Computes the Hessian using colored finite differences. 153 154 Collective on Tao 155 156 Input Parameters: 157 + tao - the Tao context 158 . V - compute Hessian at this point 159 - ctx - the PetscColoring object (must be of type MatFDColoring) 160 161 Output Parameters: 162 + H - Hessian matrix (not altered in this routine) 163 - B - newly computed Hessian matrix to use with preconditioner (generally the same as H) 164 165 Level: advanced 166 167 .seealso: TaoSetHessianRoutine(), TaoDefaultComputeHessian(),SNESComputeJacobianDefaultColor(), TaoSetGradientRoutine() 168 @*/ 169 PetscErrorCode TaoDefaultComputeHessianColor(Tao tao,Vec V,Mat H,Mat B,void *ctx) 170 { 171 PetscErrorCode ierr; 172 MatFDColoring coloring = (MatFDColoring)ctx; 173 174 PetscFunctionBegin; 175 PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_CLASSID,5); 176 ierr = PetscInfo(tao,"TAO computing matrix using finite differences Hessian and coloring\n");CHKERRQ(ierr); 177 ierr = MatFDColoringApply(B,coloring,V,ctx);CHKERRQ(ierr); 178 if (H != B) { 179 ierr = MatAssemblyBegin(H, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 180 ierr = MatAssemblyEnd(H, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 181 } 182 PetscFunctionReturn(0); 183 } 184 185 PetscErrorCode TaoDefaultComputeHessianMFFD(Tao tao,Vec X,Mat H,Mat B,void *ctx) 186 { 187 PetscInt n,N; 188 PetscErrorCode ierr; 189 190 PetscFunctionBegin; 191 if (B && B != H) SETERRQ(PetscObjectComm((PetscObject)tao),PETSC_ERR_SUP,"Preconditioning Hessian matrix"); 192 ierr = VecGetSize(X,&N);CHKERRQ(ierr); 193 ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr); 194 ierr = MatSetSizes(H,n,n,N,N);CHKERRQ(ierr); 195 ierr = MatSetType(H,MATMFFD);CHKERRQ(ierr); 196 ierr = MatSetUp(H);CHKERRQ(ierr); 197 ierr = MatMFFDSetBase(H,X,NULL);CHKERRQ(ierr); 198 ierr = MatMFFDSetFunction(H,(PetscErrorCode (*)(void*,Vec,Vec))TaoComputeGradient,tao);CHKERRQ(ierr); 199 ierr = MatAssemblyBegin(H,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 200 ierr = MatAssemblyEnd(H,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 201 PetscFunctionReturn(0); 202 } 203