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