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