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