1 #include <petsc/private/linesearchimpl.h> 2 #include <petsc/private/snesimpl.h> 3 4 typedef struct { 5 SNESLineSearchShellApplyFn *func; 6 void *ctx; 7 } SNESLineSearch_Shell; 8 9 // PetscClangLinter pragma disable: -fdoc-param-list-func-parameter-documentation 10 /*@C 11 SNESLineSearchShellSetApply - Sets the apply function for the `SNESLINESEARCHSHELL` implementation. 12 13 Not Collective 14 15 Input Parameters: 16 + linesearch - `SNESLineSearch` context 17 . func - function implementing the linesearch shell, see `SNESLineSearchShellApplyFn` for calling sequence 18 - ctx - context for func 19 20 Usage\: 21 .vb 22 PetscErrorCode shellfunc(SNESLineSearch linesearch,void * ctx) 23 { 24 Vec X,Y,F,W,G; 25 SNES snes; 26 27 PetscFunctionBegin; 28 PetscCall(SNESLineSearchGetSNES(linesearch,&snes)); 29 PetscCall(SNESLineSearchSetReason(linesearch,SNES_LINESEARCH_SUCCEEDED)); 30 PetscCall(SNESLineSearchGetVecs(linesearch,&X,&F,&Y,&W,&G)); 31 // determine lambda using W and G as work vecs.. 32 PetscCall(VecAXPY(X,-lambda,Y)); 33 PetscCall(SNESComputeFunction(snes,X,F)); 34 PetscCall(SNESLineSearchComputeNorms(linesearch)); 35 PetscFunctionReturn(PETSC_SUCCESS); 36 } 37 38 PetscCall(SNESGetLineSearch(snes, &linesearch)); 39 PetscCall(SNESLineSearchSetType(linesearch, SNESLINESEARCHSHELL)); 40 PetscCall(SNESLineSearchShellSetApply(linesearch, shellfunc, NULL)); 41 .ve 42 43 Level: advanced 44 45 .seealso: [](ch_snes), `SNESLineSearchShellGetApply()`, `SNESLINESEARCHSHELL`, `SNESLineSearchType`, `SNESLineSearch`, 46 `SNESLineSearchShellApplyFn` 47 @*/ 48 PetscErrorCode SNESLineSearchShellSetApply(SNESLineSearch linesearch, SNESLineSearchShellApplyFn *func, void *ctx) 49 { 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(PETSC_SUCCESS); 61 } 62 63 /*@C 64 SNESLineSearchShellGetApply - Gets the apply 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 it is not needed, see `SNESLineSearchShellApplyFn` for calling sequence 73 - ctx - the user function context; can be `NULL` if it is not needed 74 75 Level: advanced 76 77 .seealso: [](ch_snes), `SNESLineSearchShellSetApply()`, `SNESLINESEARCHSHELL`, `SNESLineSearchType`, `SNESLineSearch`, 78 `SNESLineSearchShellApplyFn` 79 @*/ 80 PetscErrorCode SNESLineSearchShellGetApply(SNESLineSearch linesearch, SNESLineSearchShellApplyFn **func, void **ctx) 81 { 82 PetscBool flg; 83 SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data; 84 85 PetscFunctionBegin; 86 PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1); 87 if (func) PetscAssertPointer(func, 2); 88 if (ctx) PetscAssertPointer(ctx, 3); 89 PetscCall(PetscObjectTypeCompare((PetscObject)linesearch, SNESLINESEARCHSHELL, &flg)); 90 if (flg) { 91 if (func) *func = shell->func; 92 if (ctx) *ctx = shell->ctx; 93 } 94 PetscFunctionReturn(PETSC_SUCCESS); 95 } 96 97 static PetscErrorCode SNESLineSearchApply_Shell(SNESLineSearch linesearch) 98 { 99 SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data; 100 101 PetscFunctionBegin; 102 /* apply the user function */ 103 if (shell->func) { 104 PetscCall((*shell->func)(linesearch, shell->ctx)); 105 } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "SNESLineSearchShell needs to have a shell function set with SNESLineSearchShellSetApply()"); 106 PetscFunctionReturn(PETSC_SUCCESS); 107 } 108 109 static PetscErrorCode SNESLineSearchDestroy_Shell(SNESLineSearch linesearch) 110 { 111 SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data; 112 113 PetscFunctionBegin; 114 PetscCall(PetscFree(shell)); 115 PetscFunctionReturn(PETSC_SUCCESS); 116 } 117 118 /*MC 119 SNESLINESEARCHSHELL - Provides an API for a user-provided line search routine. 120 121 Any of the other line searches may serve as a guide to how this is to be done. There is also a basic 122 template in the documentation for `SNESLineSearchShellSetApply()`. 123 124 Level: advanced 125 126 .seealso: [](ch_snes), `SNESLineSearch`, `SNES`, `SNESLineSearchCreate()`, `SNESLineSearchSetType()`, `SNESLineSearchShellSetApply()`, 127 `SNESLineSearchShellApplyFn` 128 M*/ 129 130 PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_Shell(SNESLineSearch linesearch) 131 { 132 SNESLineSearch_Shell *shell; 133 134 PetscFunctionBegin; 135 linesearch->ops->apply = SNESLineSearchApply_Shell; 136 linesearch->ops->destroy = SNESLineSearchDestroy_Shell; 137 linesearch->ops->setfromoptions = NULL; 138 linesearch->ops->reset = NULL; 139 linesearch->ops->view = NULL; 140 linesearch->ops->setup = NULL; 141 142 PetscCall(PetscNew(&shell)); 143 144 linesearch->data = (void *)shell; 145 PetscFunctionReturn(PETSC_SUCCESS); 146 } 147