1 #include <petsc/private/linesearchimpl.h> 2 #include <petsc/private/snesimpl.h> 3 4 typedef struct { 5 SNESLineSearchUserFunc func; 6 void *ctx; 7 } SNESLineSearch_Shell; 8 9 /*@C 10 SNESLineSearchShellSetUserFunc - Sets the user function for the SNESLineSearch Shell implementation. 11 12 Not Collective 13 14 Input Parameters: 15 + linesearch - SNESLineSearch context 16 . func - function implementing the linesearch shell. 17 - ctx - context for func 18 19 Calling sequence of func: 20 + linesearch - the linesearch instance 21 - ctx - the above mentioned context 22 23 Usage: 24 25 $ PetscErrorCode shellfunc(SNESLineSearch linesearch,void * ctx) 26 $ { 27 $ Vec X,Y,F,W,G; 28 $ SNES snes; 29 $ PetscFunctionBegin; 30 $ PetscCall(SNESLineSearchGetSNES(linesearch,&snes)); 31 $ PetscCall(SNESLineSearchSetReason(linesearch,SNES_LINESEARCH_SUCCEEDED)); 32 $ PetscCall(SNESLineSearchGetVecs(linesearch,&X,&F,&Y,&W,&G)); 33 $ .. determine lambda using W and G as work vecs.. 34 $ PetscCall(VecAXPY(X,-lambda,Y)); 35 $ PetscCall(SNESComputeFunction(snes,X,F)); 36 $ PetscCall(SNESLineSearchComputeNorms(linesearch)); 37 $ PetscFunctionReturn(0); 38 $ } 39 $ 40 $ ... 41 $ 42 $ PetscCall(SNESGetLineSearch(snes, &linesearch)); 43 $ PetscCall(SNESLineSearchSetType(linesearch, SNESLINESEARCHSHELL)); 44 $ PetscCall(SNESLineSearchShellSetUserFunc(linesearch, shellfunc, NULL)); 45 46 Level: advanced 47 48 .seealso: `SNESLineSearchShellGetUserFunc()`, `SNESLINESEARCHSHELL` 49 @*/ 50 PetscErrorCode SNESLineSearchShellSetUserFunc(SNESLineSearch linesearch, SNESLineSearchUserFunc func, void *ctx) 51 { 52 PetscBool flg; 53 SNESLineSearch_Shell *shell = (SNESLineSearch_Shell*)linesearch->data; 54 55 PetscFunctionBegin; 56 PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1); 57 PetscCall(PetscObjectTypeCompare((PetscObject)linesearch,SNESLINESEARCHSHELL,&flg)); 58 if (flg) { 59 shell->ctx = ctx; 60 shell->func = func; 61 } 62 PetscFunctionReturn(0); 63 } 64 65 /*@C 66 SNESLineSearchShellGetUserFunc - Gets the user function and context for the shell implementation. 67 68 Not Collective 69 70 Input Parameter: 71 . linesearch - the line search object 72 73 Output Parameters: 74 + func - the user function; can be NULL if you do not want it 75 - ctx - the user function context; can be NULL if you do not want it 76 77 Level: advanced 78 79 .seealso: `SNESLineSearchShellSetUserFunc()` 80 @*/ 81 PetscErrorCode SNESLineSearchShellGetUserFunc(SNESLineSearch linesearch, SNESLineSearchUserFunc *func, void **ctx) 82 { 83 PetscBool flg; 84 SNESLineSearch_Shell *shell = (SNESLineSearch_Shell*)linesearch->data; 85 86 PetscFunctionBegin; 87 PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1); 88 if (func) PetscValidPointer(func,2); 89 if (ctx) PetscValidPointer(ctx,3); 90 PetscCall(PetscObjectTypeCompare((PetscObject)linesearch,SNESLINESEARCHSHELL,&flg)); 91 if (flg) { 92 if (func) *func = shell->func; 93 if (ctx) *ctx = shell->ctx; 94 } 95 PetscFunctionReturn(0); 96 } 97 98 static PetscErrorCode SNESLineSearchApply_Shell(SNESLineSearch linesearch) 99 { 100 SNESLineSearch_Shell *shell = (SNESLineSearch_Shell*)linesearch->data; 101 102 PetscFunctionBegin; 103 /* apply the user function */ 104 if (shell->func) { 105 PetscCall((*shell->func)(linesearch, shell->ctx)); 106 } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "SNESLineSearchShell needs to have a shell function set with SNESLineSearchShellSetUserFunc"); 107 PetscFunctionReturn(0); 108 } 109 110 static PetscErrorCode SNESLineSearchDestroy_Shell(SNESLineSearch linesearch) 111 { 112 SNESLineSearch_Shell *shell = (SNESLineSearch_Shell*)linesearch->data; 113 114 PetscFunctionBegin; 115 PetscCall(PetscFree(shell)); 116 PetscFunctionReturn(0); 117 } 118 119 /*MC 120 SNESLINESEARCHSHELL - Provides context for a user-provided line search routine. 121 122 The user routine has one argument, the SNESLineSearch context. The user uses the interface to 123 extract line search parameters and set them accordingly when the computation is finished. 124 125 Any of the other line searches may serve as a guide to how this is to be done. There is also a basic 126 template in the documentation for SNESLineSearchShellSetUserFunc(). 127 128 Level: advanced 129 130 M*/ 131 PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_Shell(SNESLineSearch linesearch) 132 { 133 134 SNESLineSearch_Shell *shell; 135 136 PetscFunctionBegin; 137 linesearch->ops->apply = SNESLineSearchApply_Shell; 138 linesearch->ops->destroy = SNESLineSearchDestroy_Shell; 139 linesearch->ops->setfromoptions = NULL; 140 linesearch->ops->reset = NULL; 141 linesearch->ops->view = NULL; 142 linesearch->ops->setup = NULL; 143 144 PetscCall(PetscNewLog(linesearch,&shell)); 145 146 linesearch->data = (void*) shell; 147 PetscFunctionReturn(0); 148 } 149