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 SNESDestroy_Shell(SNES snes) 34 { 35 PetscFunctionBegin; 36 PetscCall(PetscFree(snes->data)); 37 PetscFunctionReturn(PETSC_SUCCESS); 38 } 39 40 static PetscErrorCode SNESSetUp_Shell(SNES snes) 41 { 42 PetscFunctionBegin; 43 PetscFunctionReturn(PETSC_SUCCESS); 44 } 45 46 static PetscErrorCode SNESSetFromOptions_Shell(SNES snes, PetscOptionItems *PetscOptionsObject) 47 { 48 PetscFunctionBegin; 49 PetscOptionsHeadBegin(PetscOptionsObject, "SNES Shell options"); 50 PetscFunctionReturn(PETSC_SUCCESS); 51 } 52 53 static PetscErrorCode SNESView_Shell(SNES snes, PetscViewer viewer) 54 { 55 PetscFunctionBegin; 56 PetscFunctionReturn(PETSC_SUCCESS); 57 } 58 59 /*@ 60 SNESShellGetContext - Returns the user-provided context associated with a `SNESSHELL` 61 62 Not Collective 63 64 Input Parameter: 65 . snes - should have been created with `SNESSetType`(snes,`SNESSHELL`); 66 67 Output Parameter: 68 . ctx - the user provided context 69 70 Level: advanced 71 72 .seealso: [](ch_snes), `SNES`, `SNESSHELL`, `SNESCreateShell()`, `SNESShellSetContext()` 73 @*/ 74 PetscErrorCode SNESShellGetContext(SNES snes, void *ctx) 75 { 76 PetscBool flg; 77 78 PetscFunctionBegin; 79 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 80 PetscAssertPointer(ctx, 2); 81 PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESSHELL, &flg)); 82 if (!flg) *(void **)ctx = NULL; 83 else *(void **)ctx = ((SNES_Shell *)snes->data)->ctx; 84 PetscFunctionReturn(PETSC_SUCCESS); 85 } 86 87 /*@ 88 SNESShellSetContext - sets the context for a `SNESSHELL` 89 90 Logically Collective 91 92 Input Parameters: 93 + snes - the `SNESSHELL` 94 - ctx - the context 95 96 Level: advanced 97 98 Fortran Note: 99 The context can only be an integer or a `PetscObject` it cannot be a Fortran array or derived type. 100 101 .seealso: [](ch_snes), `SNES`, `SNESSHELL`, `SNESCreateShell()`, `SNESShellGetContext()` 102 @*/ 103 PetscErrorCode SNESShellSetContext(SNES snes, void *ctx) 104 { 105 SNES_Shell *shell = (SNES_Shell *)snes->data; 106 PetscBool flg; 107 108 PetscFunctionBegin; 109 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 110 PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESSHELL, &flg)); 111 if (flg) shell->ctx = ctx; 112 PetscFunctionReturn(PETSC_SUCCESS); 113 } 114 115 static PetscErrorCode SNESSolve_Shell(SNES snes) 116 { 117 SNES_Shell *shell = (SNES_Shell *)snes->data; 118 119 PetscFunctionBegin; 120 PetscCheck(shell->solve, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "Must call SNESShellSetSolve() first"); 121 snes->reason = SNES_CONVERGED_ITS; 122 PetscCall((*shell->solve)(snes, snes->vec_sol)); 123 PetscFunctionReturn(PETSC_SUCCESS); 124 } 125 126 static PetscErrorCode SNESShellSetSolve_Shell(SNES snes, PetscErrorCode (*solve)(SNES, Vec)) 127 { 128 SNES_Shell *shell = (SNES_Shell *)snes->data; 129 130 PetscFunctionBegin; 131 shell->solve = solve; 132 PetscFunctionReturn(PETSC_SUCCESS); 133 } 134 135 /*MC 136 SNESSHELL - a user provided nonlinear solver 137 138 Level: advanced 139 140 .seealso: [](ch_snes), `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESType`, `SNESShellGetContext()`, `SNESShellSetContext()`, `SNESShellSetSolve()` 141 M*/ 142 143 PETSC_EXTERN PetscErrorCode SNESCreate_Shell(SNES snes) 144 { 145 SNES_Shell *shell; 146 147 PetscFunctionBegin; 148 snes->ops->destroy = SNESDestroy_Shell; 149 snes->ops->setup = SNESSetUp_Shell; 150 snes->ops->setfromoptions = SNESSetFromOptions_Shell; 151 snes->ops->view = SNESView_Shell; 152 snes->ops->solve = SNESSolve_Shell; 153 154 snes->usesksp = PETSC_FALSE; 155 snes->usesnpc = PETSC_FALSE; 156 157 snes->alwayscomputesfinalresidual = PETSC_FALSE; 158 159 PetscCall(SNESParametersInitialize(snes)); 160 161 PetscCall(PetscNew(&shell)); 162 snes->data = (void *)shell; 163 PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESShellSetSolve_C", SNESShellSetSolve_Shell)); 164 PetscFunctionReturn(PETSC_SUCCESS); 165 } 166