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 PetscFunctionBegin; 27 PetscCall(SNESLineSearchGetSNES(linesearch,&snes)); 28 PetscCall(SNESLineSearchSetReason(linesearch,SNES_LINESEARCH_SUCCEEDED)); 29 PetscCall(SNESLineSearchGetVecs(linesearch,&X,&F,&Y,&W,&G)); 30 // determine lambda using W and G as work vecs.. 31 PetscCall(VecAXPY(X,-lambda,Y)); 32 PetscCall(SNESComputeFunction(snes,X,F)); 33 PetscCall(SNESLineSearchComputeNorms(linesearch)); 34 PetscFunctionReturn(PETSC_SUCCESS); 35 } 36 37 PetscCall(SNESGetLineSearch(snes, &linesearch)); 38 PetscCall(SNESLineSearchSetType(linesearch, SNESLINESEARCHSHELL)); 39 PetscCall(SNESLineSearchShellSetApply(linesearch, shellfunc, NULL)); 40 .ve 41 42 Level: advanced 43 44 .seealso: [](ch_snes), `SNESLineSearchShellGetApply()`, `SNESLINESEARCHSHELL`, `SNESLineSearchType`, `SNESLineSearch`, 45 `SNESLineSearchShellApplyFn` 46 @*/ 47 PetscErrorCode SNESLineSearchShellSetApply(SNESLineSearch linesearch, SNESLineSearchShellApplyFn *func, void *ctx) 48 { 49 PetscBool flg; 50 SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data; 51 52 PetscFunctionBegin; 53 PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1); 54 PetscCall(PetscObjectTypeCompare((PetscObject)linesearch, SNESLINESEARCHSHELL, &flg)); 55 if (flg) { 56 shell->ctx = ctx; 57 shell->func = func; 58 } 59 PetscFunctionReturn(PETSC_SUCCESS); 60 } 61 62 /*@C 63 SNESLineSearchShellGetApply - Gets the apply function and context for the `SNESLINESEARCHSHELL` 64 65 Not Collective 66 67 Input Parameter: 68 . linesearch - the line search object 69 70 Output Parameters: 71 + func - the user function; can be `NULL` if it is not needed, see `SNESLineSearchShellApplyFn` for calling sequence 72 - ctx - the user function context; can be `NULL` if it is not needed 73 74 Level: advanced 75 76 .seealso: [](ch_snes), `SNESLineSearchShellSetApply()`, `SNESLINESEARCHSHELL`, `SNESLineSearchType`, `SNESLineSearch`, 77 `SNESLineSearchShellApplyFn` 78 @*/ 79 PetscErrorCode SNESLineSearchShellGetApply(SNESLineSearch linesearch, SNESLineSearchShellApplyFn **func, void **ctx) 80 { 81 PetscBool flg; 82 SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data; 83 84 PetscFunctionBegin; 85 PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1); 86 if (func) PetscAssertPointer(func, 2); 87 if (ctx) PetscAssertPointer(ctx, 3); 88 PetscCall(PetscObjectTypeCompare((PetscObject)linesearch, SNESLINESEARCHSHELL, &flg)); 89 if (flg) { 90 if (func) *func = shell->func; 91 if (ctx) *ctx = shell->ctx; 92 } 93 PetscFunctionReturn(PETSC_SUCCESS); 94 } 95 96 static PetscErrorCode SNESLineSearchApply_Shell(SNESLineSearch linesearch) 97 { 98 SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data; 99 100 PetscFunctionBegin; 101 /* apply the user function */ 102 if (shell->func) { 103 PetscCall((*shell->func)(linesearch, shell->ctx)); 104 } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "SNESLineSearchShell needs to have a shell function set with SNESLineSearchShellSetApply()"); 105 PetscFunctionReturn(PETSC_SUCCESS); 106 } 107 108 static PetscErrorCode SNESLineSearchDestroy_Shell(SNESLineSearch linesearch) 109 { 110 SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data; 111 112 PetscFunctionBegin; 113 PetscCall(PetscFree(shell)); 114 PetscFunctionReturn(PETSC_SUCCESS); 115 } 116 117 /*MC 118 SNESLINESEARCHSHELL - Provides an API for a user-provided line search routine. 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 `SNESLineSearchShellSetApply()`. 122 123 Level: advanced 124 125 .seealso: [](ch_snes), `SNESLineSearch`, `SNES`, `SNESLineSearchCreate()`, `SNESLineSearchSetType()`, `SNESLineSearchShellSetApply()`, 126 `SNESLineSearchShellApplyFn` 127 M*/ 128 129 PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_Shell(SNESLineSearch linesearch) 130 { 131 SNESLineSearch_Shell *shell; 132 133 PetscFunctionBegin; 134 linesearch->ops->apply = SNESLineSearchApply_Shell; 135 linesearch->ops->destroy = SNESLineSearchDestroy_Shell; 136 linesearch->ops->setfromoptions = NULL; 137 linesearch->ops->reset = NULL; 138 linesearch->ops->view = NULL; 139 linesearch->ops->setup = NULL; 140 141 PetscCall(PetscNew(&shell)); 142 143 linesearch->data = (void *)shell; 144 PetscFunctionReturn(PETSC_SUCCESS); 145 } 146