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