1af0996ceSBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/ 2074cc835SBarry Smith 39371c9d4SSatish Balay typedef struct { 49371c9d4SSatish Balay PetscErrorCode (*solve)(SNES, Vec); 5*2a8381b2SBarry Smith PetscCtx ctx; 69371c9d4SSatish Balay } SNES_Shell; 7074cc835SBarry Smith 8074cc835SBarry Smith /*@C 9ceaaa498SBarry Smith SNESShellSetSolve - Sets routine to apply as solver to a `SNESSHELL` `SNES` object 10074cc835SBarry Smith 11c3339decSBarry Smith Logically Collective 12074cc835SBarry Smith 13074cc835SBarry Smith Input Parameters: 14f6dfbefdSBarry Smith + snes - the `SNES` nonlinear solver context 15ceaaa498SBarry Smith - solve - the application-provided solver routine 16074cc835SBarry Smith 1720f4b53cSBarry Smith Calling sequence of `apply`: 1854c05997SPierre Jolivet + snes - the preconditioner, get the application context with `SNESShellGetContext()` provided with `SNESShellSetContext()` 19ceaaa498SBarry Smith - xout - solution vector 20074cc835SBarry Smith 21074cc835SBarry Smith Level: advanced 22074cc835SBarry Smith 23420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSHELL`, `SNESShellSetContext()`, `SNESShellGetContext()` 24074cc835SBarry Smith @*/ 25ceaaa498SBarry Smith PetscErrorCode SNESShellSetSolve(SNES snes, PetscErrorCode (*solve)(SNES snes, Vec xout)) 26d71ae5a4SJacob Faibussowitsch { 27074cc835SBarry Smith PetscFunctionBegin; 28074cc835SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 29cac4c232SBarry Smith PetscTryMethod(snes, "SNESShellSetSolve_C", (SNES, PetscErrorCode (*)(SNES, Vec)), (snes, solve)); 303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31074cc835SBarry Smith } 32074cc835SBarry Smith 3366976f2fSJacob Faibussowitsch static PetscErrorCode SNESDestroy_Shell(SNES snes) 34d71ae5a4SJacob Faibussowitsch { 35074cc835SBarry Smith PetscFunctionBegin; 369566063dSJacob Faibussowitsch PetscCall(PetscFree(snes->data)); 373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 38074cc835SBarry Smith } 39074cc835SBarry Smith 4090b77ac2SPeter Brune /*@ 41f6dfbefdSBarry Smith SNESShellGetContext - Returns the user-provided context associated with a `SNESSHELL` 42074cc835SBarry Smith 43074cc835SBarry Smith Not Collective 44074cc835SBarry Smith 45074cc835SBarry Smith Input Parameter: 46f6dfbefdSBarry Smith . snes - should have been created with `SNESSetType`(snes,`SNESSHELL`); 47074cc835SBarry Smith 48074cc835SBarry Smith Output Parameter: 49074cc835SBarry Smith . ctx - the user provided context 50074cc835SBarry Smith 51074cc835SBarry Smith Level: advanced 52074cc835SBarry Smith 53*2a8381b2SBarry Smith Fortran Notes: 54*2a8381b2SBarry Smith This only works when the context is a Fortran derived type or a `PetscObject`. Declare `ctx` with 55*2a8381b2SBarry Smith .vb 56*2a8381b2SBarry Smith type(tUsertype), pointer :: ctx 57*2a8381b2SBarry Smith .ve 58*2a8381b2SBarry Smith 59420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSHELL`, `SNESCreateShell()`, `SNESShellSetContext()` 60074cc835SBarry Smith @*/ 61*2a8381b2SBarry Smith PetscErrorCode SNESShellGetContext(SNES snes, PetscCtxRt ctx) 62d71ae5a4SJacob Faibussowitsch { 63074cc835SBarry Smith PetscBool flg; 64074cc835SBarry Smith 65074cc835SBarry Smith PetscFunctionBegin; 66074cc835SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 674f572ea9SToby Isaac PetscAssertPointer(ctx, 2); 689566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESSHELL, &flg)); 693ec1f749SStefano Zampini if (!flg) *(void **)ctx = NULL; 70f4f49eeaSPierre Jolivet else *(void **)ctx = ((SNES_Shell *)snes->data)->ctx; 713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 72074cc835SBarry Smith } 73074cc835SBarry Smith 74074cc835SBarry Smith /*@ 75f6dfbefdSBarry Smith SNESShellSetContext - sets the context for a `SNESSHELL` 76074cc835SBarry Smith 77c3339decSBarry Smith Logically Collective 78074cc835SBarry Smith 79074cc835SBarry Smith Input Parameters: 80f6dfbefdSBarry Smith + snes - the `SNESSHELL` 81074cc835SBarry Smith - ctx - the context 82074cc835SBarry Smith 83074cc835SBarry Smith Level: advanced 84074cc835SBarry Smith 85420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSHELL`, `SNESCreateShell()`, `SNESShellGetContext()` 86074cc835SBarry Smith @*/ 87*2a8381b2SBarry Smith PetscErrorCode SNESShellSetContext(SNES snes, PetscCtx ctx) 88d71ae5a4SJacob Faibussowitsch { 89074cc835SBarry Smith SNES_Shell *shell = (SNES_Shell *)snes->data; 90074cc835SBarry Smith PetscBool flg; 91074cc835SBarry Smith 92074cc835SBarry Smith PetscFunctionBegin; 93074cc835SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 949566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESSHELL, &flg)); 951aa26658SKarl Rupp if (flg) shell->ctx = ctx; 963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 97074cc835SBarry Smith } 98074cc835SBarry Smith 9966976f2fSJacob Faibussowitsch static PetscErrorCode SNESSolve_Shell(SNES snes) 100d71ae5a4SJacob Faibussowitsch { 101074cc835SBarry Smith SNES_Shell *shell = (SNES_Shell *)snes->data; 102074cc835SBarry Smith 103074cc835SBarry Smith PetscFunctionBegin; 10428b400f6SJacob Faibussowitsch PetscCheck(shell->solve, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "Must call SNESShellSetSolve() first"); 1051e633543SBarry Smith snes->reason = SNES_CONVERGED_ITS; 1069566063dSJacob Faibussowitsch PetscCall((*shell->solve)(snes, snes->vec_sol)); 1073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 108074cc835SBarry Smith } 109074cc835SBarry Smith 11066976f2fSJacob Faibussowitsch static PetscErrorCode SNESShellSetSolve_Shell(SNES snes, PetscErrorCode (*solve)(SNES, Vec)) 111d71ae5a4SJacob Faibussowitsch { 112074cc835SBarry Smith SNES_Shell *shell = (SNES_Shell *)snes->data; 113074cc835SBarry Smith 114074cc835SBarry Smith PetscFunctionBegin; 115074cc835SBarry Smith shell->solve = solve; 1163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 117074cc835SBarry Smith } 118074cc835SBarry Smith 119074cc835SBarry Smith /*MC 120074cc835SBarry Smith SNESSHELL - a user provided nonlinear solver 121074cc835SBarry Smith 122074cc835SBarry Smith Level: advanced 123074cc835SBarry Smith 124420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESType`, `SNESShellGetContext()`, `SNESShellSetContext()`, `SNESShellSetSolve()` 125074cc835SBarry Smith M*/ 126074cc835SBarry Smith 127d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode SNESCreate_Shell(SNES snes) 128d71ae5a4SJacob Faibussowitsch { 129074cc835SBarry Smith SNES_Shell *shell; 130074cc835SBarry Smith 131074cc835SBarry Smith PetscFunctionBegin; 132074cc835SBarry Smith snes->ops->destroy = SNESDestroy_Shell; 133074cc835SBarry Smith snes->ops->solve = SNESSolve_Shell; 134074cc835SBarry Smith 135074cc835SBarry Smith snes->usesksp = PETSC_FALSE; 136efd4aadfSBarry Smith snes->usesnpc = PETSC_FALSE; 137074cc835SBarry Smith 1384fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 1394fc747eaSLawrence Mitchell 14077e5a1f9SBarry Smith PetscCall(SNESParametersInitialize(snes)); 14177e5a1f9SBarry Smith 1424dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&shell)); 143074cc835SBarry Smith snes->data = (void *)shell; 1449566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESShellSetSolve_C", SNESShellSetSolve_Shell)); 1453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 146074cc835SBarry Smith } 147