1 #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/ 2 3 typedef struct { 4 PetscErrorCode (*solve)(SNES, Vec); 5 void *ctx; 6 } SNES_Shell; 7 8 /*@C 9 SNESShellSetSolve - Sets routine to apply as solver to a `SNESSHELL` `SNES` object 10 11 Logically Collective 12 13 Input Parameters: 14 + snes - the `SNES` nonlinear solver context 15 - solve - the application-provided solver routine 16 17 Calling sequence of `apply`: 18 + snes - the preconditioner, get the application context with `SNESShellGetContext()` provided with `SNESShelletContext()` 19 - xout - solution vector 20 21 Level: advanced 22 23 .seealso: [](ch_snes), `SNES`, `SNESSHELL`, `SNESShellSetContext()`, `SNESShellGetContext()` 24 @*/ 25 PetscErrorCode SNESShellSetSolve(SNES snes, PetscErrorCode (*solve)(SNES snes, Vec xout)) 26 { 27 PetscFunctionBegin; 28 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 29 PetscTryMethod(snes, "SNESShellSetSolve_C", (SNES, PetscErrorCode(*)(SNES, Vec)), (snes, solve)); 30 PetscFunctionReturn(PETSC_SUCCESS); 31 } 32 33 static PetscErrorCode SNESReset_Shell(SNES snes) 34 { 35 PetscFunctionBegin; 36 PetscFunctionReturn(PETSC_SUCCESS); 37 } 38 39 static PetscErrorCode SNESDestroy_Shell(SNES snes) 40 { 41 PetscFunctionBegin; 42 PetscCall(SNESReset_Shell(snes)); 43 PetscCall(PetscFree(snes->data)); 44 PetscFunctionReturn(PETSC_SUCCESS); 45 } 46 47 static PetscErrorCode SNESSetUp_Shell(SNES snes) 48 { 49 PetscFunctionBegin; 50 PetscFunctionReturn(PETSC_SUCCESS); 51 } 52 53 static PetscErrorCode SNESSetFromOptions_Shell(SNES snes, PetscOptionItems *PetscOptionsObject) 54 { 55 PetscFunctionBegin; 56 PetscOptionsHeadBegin(PetscOptionsObject, "SNES Shell options"); 57 PetscFunctionReturn(PETSC_SUCCESS); 58 } 59 60 static PetscErrorCode SNESView_Shell(SNES snes, PetscViewer viewer) 61 { 62 PetscFunctionBegin; 63 PetscFunctionReturn(PETSC_SUCCESS); 64 } 65 66 /*@ 67 SNESShellGetContext - Returns the user-provided context associated with a `SNESSHELL` 68 69 Not Collective 70 71 Input Parameter: 72 . snes - should have been created with `SNESSetType`(snes,`SNESSHELL`); 73 74 Output Parameter: 75 . ctx - the user provided context 76 77 Level: advanced 78 79 .seealso: [](ch_snes), `SNES`, `SNESSHELL`, `SNESCreateShell()`, `SNESShellSetContext()` 80 @*/ 81 PetscErrorCode SNESShellGetContext(SNES snes, void *ctx) 82 { 83 PetscBool flg; 84 85 PetscFunctionBegin; 86 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 87 PetscAssertPointer(ctx, 2); 88 PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESSHELL, &flg)); 89 if (!flg) *(void **)ctx = NULL; 90 else *(void **)ctx = ((SNES_Shell *)snes->data)->ctx; 91 PetscFunctionReturn(PETSC_SUCCESS); 92 } 93 94 /*@ 95 SNESShellSetContext - sets the context for a `SNESSHELL` 96 97 Logically Collective 98 99 Input Parameters: 100 + snes - the `SNESSHELL` 101 - ctx - the context 102 103 Level: advanced 104 105 Fortran Note: 106 The context can only be an integer or a `PetscObject` it cannot be a Fortran array or derived type. 107 108 .seealso: [](ch_snes), `SNES`, `SNESSHELL`, `SNESCreateShell()`, `SNESShellGetContext()` 109 @*/ 110 PetscErrorCode SNESShellSetContext(SNES snes, void *ctx) 111 { 112 SNES_Shell *shell = (SNES_Shell *)snes->data; 113 PetscBool flg; 114 115 PetscFunctionBegin; 116 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 117 PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESSHELL, &flg)); 118 if (flg) shell->ctx = ctx; 119 PetscFunctionReturn(PETSC_SUCCESS); 120 } 121 122 static PetscErrorCode SNESSolve_Shell(SNES snes) 123 { 124 SNES_Shell *shell = (SNES_Shell *)snes->data; 125 126 PetscFunctionBegin; 127 PetscCheck(shell->solve, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "Must call SNESShellSetSolve() first"); 128 snes->reason = SNES_CONVERGED_ITS; 129 PetscCall((*shell->solve)(snes, snes->vec_sol)); 130 PetscFunctionReturn(PETSC_SUCCESS); 131 } 132 133 static PetscErrorCode SNESShellSetSolve_Shell(SNES snes, PetscErrorCode (*solve)(SNES, Vec)) 134 { 135 SNES_Shell *shell = (SNES_Shell *)snes->data; 136 137 PetscFunctionBegin; 138 shell->solve = solve; 139 PetscFunctionReturn(PETSC_SUCCESS); 140 } 141 142 /*MC 143 SNESSHELL - a user provided nonlinear solver 144 145 Level: advanced 146 147 .seealso: [](ch_snes), `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESType`, `SNESShellGetContext()`, `SNESShellSetContext()`, `SNESShellSetSolve()` 148 M*/ 149 150 PETSC_EXTERN PetscErrorCode SNESCreate_Shell(SNES snes) 151 { 152 SNES_Shell *shell; 153 154 PetscFunctionBegin; 155 snes->ops->destroy = SNESDestroy_Shell; 156 snes->ops->setup = SNESSetUp_Shell; 157 snes->ops->setfromoptions = SNESSetFromOptions_Shell; 158 snes->ops->view = SNESView_Shell; 159 snes->ops->solve = SNESSolve_Shell; 160 snes->ops->reset = SNESReset_Shell; 161 162 snes->usesksp = PETSC_FALSE; 163 snes->usesnpc = PETSC_FALSE; 164 165 snes->alwayscomputesfinalresidual = PETSC_FALSE; 166 167 PetscCall(PetscNew(&shell)); 168 snes->data = (void *)shell; 169 PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESShellSetSolve_C", SNESShellSetSolve_Shell)); 170 PetscFunctionReturn(PETSC_SUCCESS); 171 } 172