16cab3a1bSJed Brown #include <petscdmda.h> /*I "petscdmda.h" I*/ 2af0996ceSBarry Smith #include <petsc/private/dmimpl.h> 3af0996ceSBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/ 46cab3a1bSJed Brown 56cab3a1bSJed Brown /* This structure holds the user-provided DMDA callbacks */ 66cab3a1bSJed Brown typedef struct { 76cab3a1bSJed Brown PetscErrorCode (*residuallocal)(DMDALocalInfo *, void *, void *, void *); 8d1e9a80fSBarry Smith PetscErrorCode (*jacobianlocal)(DMDALocalInfo *, void *, Mat, Mat, void *); 92a4ee8f2SPeter Brune PetscErrorCode (*objectivelocal)(DMDALocalInfo *, void *, PetscReal *, void *); 105505f7afSJunchao Zhang 115505f7afSJunchao Zhang PetscErrorCode (*residuallocalvec)(DMDALocalInfo *, Vec, Vec, void *); 125505f7afSJunchao Zhang PetscErrorCode (*jacobianlocalvec)(DMDALocalInfo *, Vec, Mat, Mat, void *); 135505f7afSJunchao Zhang PetscErrorCode (*objectivelocalvec)(DMDALocalInfo *, Vec, PetscReal *, void *); 146cab3a1bSJed Brown void *residuallocalctx; 156cab3a1bSJed Brown void *jacobianlocalctx; 162a4ee8f2SPeter Brune void *objectivelocalctx; 17709ac0d2SJed Brown InsertMode residuallocalimode; 18dcad5f1cSBarry Smith 19dcad5f1cSBarry Smith /* For Picard iteration defined locally */ 20dcad5f1cSBarry Smith PetscErrorCode (*rhsplocal)(DMDALocalInfo *, void *, void *, void *); 21d1e9a80fSBarry Smith PetscErrorCode (*jacobianplocal)(DMDALocalInfo *, void *, Mat, Mat, void *); 22dcad5f1cSBarry Smith void *picardlocalctx; 23942e3340SBarry Smith } DMSNES_DA; 246cab3a1bSJed Brown 25d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSNESDestroy_DMDA(DMSNES sdm) 26d71ae5a4SJacob Faibussowitsch { 276cab3a1bSJed Brown PetscFunctionBegin; 289566063dSJacob Faibussowitsch PetscCall(PetscFree(sdm->data)); 29*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 306cab3a1bSJed Brown } 316cab3a1bSJed Brown 32d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSNESDuplicate_DMDA(DMSNES oldsdm, DMSNES sdm) 33d71ae5a4SJacob Faibussowitsch { 34e3c0b8a2SPeter Brune PetscFunctionBegin; 354dfa11a4SJacob Faibussowitsch PetscCall(PetscNew((DMSNES_DA **)&sdm->data)); 361baa6e33SBarry Smith if (oldsdm->data) PetscCall(PetscMemcpy(sdm->data, oldsdm->data, sizeof(DMSNES_DA))); 37*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 38e3c0b8a2SPeter Brune } 39e3c0b8a2SPeter Brune 40d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMDASNESGetContext(DM dm, DMSNES sdm, DMSNES_DA **dmdasnes) 41d71ae5a4SJacob Faibussowitsch { 426cab3a1bSJed Brown PetscFunctionBegin; 430298fd71SBarry Smith *dmdasnes = NULL; 446cab3a1bSJed Brown if (!sdm->data) { 454dfa11a4SJacob Faibussowitsch PetscCall(PetscNew((DMSNES_DA **)&sdm->data)); 4622c6f798SBarry Smith sdm->ops->destroy = DMSNESDestroy_DMDA; 4722c6f798SBarry Smith sdm->ops->duplicate = DMSNESDuplicate_DMDA; 486cab3a1bSJed Brown } 49942e3340SBarry Smith *dmdasnes = (DMSNES_DA *)sdm->data; 50*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 516cab3a1bSJed Brown } 526cab3a1bSJed Brown 53d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESComputeFunction_DMDA(SNES snes, Vec X, Vec F, void *ctx) 54d71ae5a4SJacob Faibussowitsch { 556cab3a1bSJed Brown DM dm; 56942e3340SBarry Smith DMSNES_DA *dmdasnes = (DMSNES_DA *)ctx; 576cab3a1bSJed Brown DMDALocalInfo info; 586cab3a1bSJed Brown Vec Xloc; 596cab3a1bSJed Brown void *x, *f; 606cab3a1bSJed Brown 616cab3a1bSJed Brown PetscFunctionBegin; 622961e153SJed Brown PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 632961e153SJed Brown PetscValidHeaderSpecific(X, VEC_CLASSID, 2); 642961e153SJed Brown PetscValidHeaderSpecific(F, VEC_CLASSID, 3); 655505f7afSJunchao Zhang PetscCheck(dmdasnes->residuallocal || dmdasnes->residuallocalvec, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "Corrupt context"); 669566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 679566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &Xloc)); 689566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, X, INSERT_VALUES, Xloc)); 699566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, X, INSERT_VALUES, Xloc)); 709566063dSJacob Faibussowitsch PetscCall(DMDAGetLocalInfo(dm, &info)); 71709ac0d2SJed Brown switch (dmdasnes->residuallocalimode) { 72709ac0d2SJed Brown case INSERT_VALUES: { 739566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, X, F, 0)); 74792fecdfSBarry Smith if (dmdasnes->residuallocalvec) PetscCallBack("SNES DMDA local callback function", (*dmdasnes->residuallocalvec)(&info, Xloc, F, dmdasnes->residuallocalctx)); 75ef1023bdSBarry Smith else { 765505f7afSJunchao Zhang PetscCall(DMDAVecGetArray(dm, Xloc, &x)); 775505f7afSJunchao Zhang PetscCall(DMDAVecGetArray(dm, F, &f)); 78792fecdfSBarry Smith PetscCallBack("SNES DMDA local callback function", (*dmdasnes->residuallocal)(&info, x, f, dmdasnes->residuallocalctx)); 795505f7afSJunchao Zhang PetscCall(DMDAVecRestoreArray(dm, Xloc, &x)); 805505f7afSJunchao Zhang PetscCall(DMDAVecRestoreArray(dm, F, &f)); 815505f7afSJunchao Zhang } 829566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, X, F, 0)); 83709ac0d2SJed Brown } break; 84709ac0d2SJed Brown case ADD_VALUES: { 85709ac0d2SJed Brown Vec Floc; 869566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &Floc)); 879566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Floc)); 889566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, X, F, 0)); 89792fecdfSBarry Smith if (dmdasnes->residuallocalvec) PetscCallBack("SNES DMDA local callback function", (*dmdasnes->residuallocalvec)(&info, Xloc, Floc, dmdasnes->residuallocalctx)); 90ef1023bdSBarry Smith else { 915505f7afSJunchao Zhang PetscCall(DMDAVecGetArray(dm, Xloc, &x)); 925505f7afSJunchao Zhang PetscCall(DMDAVecGetArray(dm, Floc, &f)); 93792fecdfSBarry Smith PetscCallBack("SNES DMDA local callback function", (*dmdasnes->residuallocal)(&info, x, f, dmdasnes->residuallocalctx)); 945505f7afSJunchao Zhang PetscCall(DMDAVecRestoreArray(dm, Xloc, &x)); 955505f7afSJunchao Zhang PetscCall(DMDAVecRestoreArray(dm, Floc, &f)); 965505f7afSJunchao Zhang } 979566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, X, F, 0)); 989566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(F)); 999566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dm, Floc, ADD_VALUES, F)); 1009566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dm, Floc, ADD_VALUES, F)); 1019566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &Floc)); 102709ac0d2SJed Brown } break; 103d71ae5a4SJacob Faibussowitsch default: 104d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "Cannot use imode=%d", (int)dmdasnes->residuallocalimode); 105709ac0d2SJed Brown } 1069566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &Xloc)); 1071baa6e33SBarry Smith if (snes->domainerror) PetscCall(VecSetInf(F)); 108*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1096cab3a1bSJed Brown } 1106cab3a1bSJed Brown 111d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESComputeObjective_DMDA(SNES snes, Vec X, PetscReal *ob, void *ctx) 112d71ae5a4SJacob Faibussowitsch { 1132a4ee8f2SPeter Brune DM dm; 114942e3340SBarry Smith DMSNES_DA *dmdasnes = (DMSNES_DA *)ctx; 1152a4ee8f2SPeter Brune DMDALocalInfo info; 1162a4ee8f2SPeter Brune Vec Xloc; 1172a4ee8f2SPeter Brune void *x; 1182a4ee8f2SPeter Brune 1192a4ee8f2SPeter Brune PetscFunctionBegin; 1202a4ee8f2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1212a4ee8f2SPeter Brune PetscValidHeaderSpecific(X, VEC_CLASSID, 2); 122dadcf809SJacob Faibussowitsch PetscValidRealPointer(ob, 3); 1235505f7afSJunchao Zhang PetscCheck(dmdasnes->objectivelocal || dmdasnes->objectivelocalvec, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "Corrupt context"); 1249566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 1259566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &Xloc)); 1269566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, X, INSERT_VALUES, Xloc)); 1279566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, X, INSERT_VALUES, Xloc)); 1289566063dSJacob Faibussowitsch PetscCall(DMDAGetLocalInfo(dm, &info)); 129792fecdfSBarry Smith if (dmdasnes->objectivelocalvec) PetscCallBack("SNES DMDA local callback objective", (*dmdasnes->objectivelocalvec)(&info, Xloc, ob, dmdasnes->objectivelocalctx)); 130ef1023bdSBarry Smith else { 1319566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(dm, Xloc, &x)); 132792fecdfSBarry Smith PetscCallBack("SNES DMDA local callback objective", (*dmdasnes->objectivelocal)(&info, x, ob, dmdasnes->objectivelocalctx)); 1339566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(dm, Xloc, &x)); 1345505f7afSJunchao Zhang } 1359566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &Xloc)); 136*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1372a4ee8f2SPeter Brune } 1382a4ee8f2SPeter Brune 139cc2e6a90SBarry Smith /* Routine is called by example, hence must be labeled PETSC_EXTERN */ 140d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode SNESComputeJacobian_DMDA(SNES snes, Vec X, Mat A, Mat B, void *ctx) 141d71ae5a4SJacob Faibussowitsch { 1422961e153SJed Brown DM dm; 143942e3340SBarry Smith DMSNES_DA *dmdasnes = (DMSNES_DA *)ctx; 1442961e153SJed Brown DMDALocalInfo info; 1452961e153SJed Brown Vec Xloc; 1462961e153SJed Brown void *x; 1472961e153SJed Brown 1482961e153SJed Brown PetscFunctionBegin; 1495505f7afSJunchao Zhang PetscCheck(dmdasnes->residuallocal || dmdasnes->residuallocalvec, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "Corrupt context"); 1509566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 1512961e153SJed Brown 1525505f7afSJunchao Zhang if (dmdasnes->jacobianlocal || dmdasnes->jacobianlocalctx) { 1539566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &Xloc)); 1549566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, X, INSERT_VALUES, Xloc)); 1559566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, X, INSERT_VALUES, Xloc)); 1569566063dSJacob Faibussowitsch PetscCall(DMDAGetLocalInfo(dm, &info)); 157792fecdfSBarry Smith if (dmdasnes->jacobianlocalvec) PetscCallBack("SNES DMDA local callback Jacobian", (*dmdasnes->jacobianlocalvec)(&info, Xloc, A, B, dmdasnes->jacobianlocalctx)); 158ef1023bdSBarry Smith else { 1599566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(dm, Xloc, &x)); 160792fecdfSBarry Smith PetscCallBack("SNES DMDA local callback Jacobian", (*dmdasnes->jacobianlocal)(&info, x, A, B, dmdasnes->jacobianlocalctx)); 1619566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(dm, Xloc, &x)); 1625505f7afSJunchao Zhang } 1639566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &Xloc)); 1642961e153SJed Brown } else { 1652961e153SJed Brown MatFDColoring fdcoloring; 1669566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)dm, "DMDASNES_FDCOLORING", (PetscObject *)&fdcoloring)); 1672961e153SJed Brown if (!fdcoloring) { 1682961e153SJed Brown ISColoring coloring; 1692961e153SJed Brown 1709566063dSJacob Faibussowitsch PetscCall(DMCreateColoring(dm, dm->coloringtype, &coloring)); 1719566063dSJacob Faibussowitsch PetscCall(MatFDColoringCreate(B, coloring, &fdcoloring)); 1722961e153SJed Brown switch (dm->coloringtype) { 173d71ae5a4SJacob Faibussowitsch case IS_COLORING_GLOBAL: 174d71ae5a4SJacob Faibussowitsch PetscCall(MatFDColoringSetFunction(fdcoloring, (PetscErrorCode(*)(void))SNESComputeFunction_DMDA, dmdasnes)); 175d71ae5a4SJacob Faibussowitsch break; 176d71ae5a4SJacob Faibussowitsch default: 177d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)snes), PETSC_ERR_SUP, "No support for coloring type '%s'", ISColoringTypes[dm->coloringtype]); 1782961e153SJed Brown } 1799566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fdcoloring, ((PetscObject)dm)->prefix)); 1809566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(fdcoloring)); 1819566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetUp(B, coloring, fdcoloring)); 1829566063dSJacob Faibussowitsch PetscCall(ISColoringDestroy(&coloring)); 1839566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "DMDASNES_FDCOLORING", (PetscObject)fdcoloring)); 1849566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)fdcoloring)); 1852961e153SJed Brown 1862961e153SJed Brown /* The following breaks an ugly reference counting loop that deserves a paragraph. MatFDColoringApply() will call 1872961e153SJed Brown * VecDuplicate() with the state Vec and store inside the MatFDColoring. This Vec will duplicate the Vec, but the 1882961e153SJed Brown * MatFDColoring is composed with the DM. We dereference the DM here so that the reference count will eventually 1892961e153SJed Brown * drop to 0. Note the code in DMDestroy() that exits early for a negative reference count. That code path will be 190140e18c1SBarry Smith * taken when the PetscObjectList for the Vec inside MatFDColoring is destroyed. 1912961e153SJed Brown */ 1929566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)dm)); 1932961e153SJed Brown } 1949566063dSJacob Faibussowitsch PetscCall(MatFDColoringApply(B, fdcoloring, X, snes)); 1952961e153SJed Brown } 1962961e153SJed Brown /* This will be redundant if the user called both, but it's too common to forget. */ 19794ab13aaSBarry Smith if (A != B) { 1989566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 1999566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2002961e153SJed Brown } 201*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2022961e153SJed Brown } 2032961e153SJed Brown 2046cab3a1bSJed Brown /*@C 205f6dfbefdSBarry Smith DMDASNESSetFunctionLocal - set a local residual evaluation function for use with `DMDA` 2066cab3a1bSJed Brown 2076cab3a1bSJed Brown Logically Collective 2086cab3a1bSJed Brown 2094165533cSJose E. Roman Input Parameters: 210f6dfbefdSBarry Smith + dm - `DM` to associate callback with 211f6dfbefdSBarry Smith . imode - `INSERT_VALUES` if local function computes owned part, `ADD_VALUES` if it contributes to ghosted part 2126cab3a1bSJed Brown . func - local residual evaluation 2136cab3a1bSJed Brown - ctx - optional context for local residual evaluation 2146cab3a1bSJed Brown 2150038884cSBarry Smith Calling sequence: 2160038884cSBarry Smith For PetscErrorCode (*func)(DMDALocalInfo *info,void *x, void *f, void *ctx), 217f6dfbefdSBarry Smith + info - `DMDALocalInfo` defining the subdomain to evaluate the residual on 2180038884cSBarry Smith . x - dimensional pointer to state at which to evaluate residual (e.g. PetscScalar *x or **x or ***x) 2190038884cSBarry Smith . f - dimensional pointer to residual, write the residual here (e.g. PetscScalar *f or **f or ***f) 2206cab3a1bSJed Brown - ctx - optional context passed above 2216cab3a1bSJed Brown 2226cab3a1bSJed Brown Level: beginner 2236cab3a1bSJed Brown 224f6dfbefdSBarry Smith .seealso: `DMDA`, `DMDASNESSetJacobianLocal()`, `DMSNESSetFunction()`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()` 2256cab3a1bSJed Brown @*/ 226d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDASNESSetFunctionLocal(DM dm, InsertMode imode, PetscErrorCode (*func)(DMDALocalInfo *, void *, void *, void *), void *ctx) 227d71ae5a4SJacob Faibussowitsch { 228942e3340SBarry Smith DMSNES sdm; 229942e3340SBarry Smith DMSNES_DA *dmdasnes; 2306cab3a1bSJed Brown 2316cab3a1bSJed Brown PetscFunctionBegin; 2326cab3a1bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2339566063dSJacob Faibussowitsch PetscCall(DMGetDMSNESWrite(dm, &sdm)); 2349566063dSJacob Faibussowitsch PetscCall(DMDASNESGetContext(dm, sdm, &dmdasnes)); 2351aa26658SKarl Rupp 236709ac0d2SJed Brown dmdasnes->residuallocalimode = imode; 2376cab3a1bSJed Brown dmdasnes->residuallocal = func; 2386cab3a1bSJed Brown dmdasnes->residuallocalctx = ctx; 2391aa26658SKarl Rupp 2409566063dSJacob Faibussowitsch PetscCall(DMSNESSetFunction(dm, SNESComputeFunction_DMDA, dmdasnes)); 24122c6f798SBarry Smith if (!sdm->ops->computejacobian) { /* Call us for the Jacobian too, can be overridden by the user. */ 2429566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobian_DMDA, dmdasnes)); 2432961e153SJed Brown } 244*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2452961e153SJed Brown } 2462961e153SJed Brown 2472961e153SJed Brown /*@C 248f6dfbefdSBarry Smith DMDASNESSetFunctionLocalVec - set a local residual evaluation function that operates on a local vector for `DMDA` 2495505f7afSJunchao Zhang 2505505f7afSJunchao Zhang Logically Collective 2515505f7afSJunchao Zhang 2525505f7afSJunchao Zhang Input Parameters: 253f6dfbefdSBarry Smith + dm - `DM` to associate callback with 254f6dfbefdSBarry Smith . imode - `INSERT_VALUES` if local function computes owned part, `ADD_VALUES` if it contributes to ghosted part 2555505f7afSJunchao Zhang . func - local residual evaluation 2565505f7afSJunchao Zhang - ctx - optional context for local residual evaluation 2575505f7afSJunchao Zhang 2585505f7afSJunchao Zhang Calling sequence: 2595505f7afSJunchao Zhang For PetscErrorCode (*func)(DMDALocalInfo *info,Vec x, Vec f, void *ctx), 260f6dfbefdSBarry Smith + info - `DMDALocalInfo` defining the subdomain to evaluate the residual on 2615505f7afSJunchao Zhang . x - state vector at which to evaluate residual 2625505f7afSJunchao Zhang . f - residual vector 2635505f7afSJunchao Zhang - ctx - optional context passed above 2645505f7afSJunchao Zhang 2655505f7afSJunchao Zhang Level: beginner 2665505f7afSJunchao Zhang 267f6dfbefdSBarry Smith .seealso: `DMDA`, `DMDASNESSetFunctionLocal()`, `DMDASNESSetJacobianLocalVec()`, `DMSNESSetFunction()`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()` 2685505f7afSJunchao Zhang @*/ 269d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDASNESSetFunctionLocalVec(DM dm, InsertMode imode, PetscErrorCode (*func)(DMDALocalInfo *, Vec, Vec, void *), void *ctx) 270d71ae5a4SJacob Faibussowitsch { 2715505f7afSJunchao Zhang DMSNES sdm; 2725505f7afSJunchao Zhang DMSNES_DA *dmdasnes; 2735505f7afSJunchao Zhang 2745505f7afSJunchao Zhang PetscFunctionBegin; 2755505f7afSJunchao Zhang PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2765505f7afSJunchao Zhang PetscCall(DMGetDMSNESWrite(dm, &sdm)); 2775505f7afSJunchao Zhang PetscCall(DMDASNESGetContext(dm, sdm, &dmdasnes)); 2785505f7afSJunchao Zhang 2795505f7afSJunchao Zhang dmdasnes->residuallocalimode = imode; 2805505f7afSJunchao Zhang dmdasnes->residuallocalvec = func; 2815505f7afSJunchao Zhang dmdasnes->residuallocalctx = ctx; 2825505f7afSJunchao Zhang 2835505f7afSJunchao Zhang PetscCall(DMSNESSetFunction(dm, SNESComputeFunction_DMDA, dmdasnes)); 2845505f7afSJunchao Zhang if (!sdm->ops->computejacobian) { /* Call us for the Jacobian too, can be overridden by the user. */ 2855505f7afSJunchao Zhang PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobian_DMDA, dmdasnes)); 2865505f7afSJunchao Zhang } 287*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2885505f7afSJunchao Zhang } 2895505f7afSJunchao Zhang 2905505f7afSJunchao Zhang /*@C 291f6dfbefdSBarry Smith DMDASNESSetJacobianLocal - set a local Jacobian evaluation function for use with `DMDA` 2922961e153SJed Brown 2932961e153SJed Brown Logically Collective 2942961e153SJed Brown 2954165533cSJose E. Roman Input Parameters: 296f6dfbefdSBarry Smith + dm - `DM` to associate callback with 2976b7eb5ceSMatthew G. Knepley . func - local Jacobian evaluation 2986b7eb5ceSMatthew G. Knepley - ctx - optional context for local Jacobian evaluation 2992961e153SJed Brown 3000038884cSBarry Smith Calling sequence: 3010038884cSBarry Smith For PetscErrorCode (*func)(DMDALocalInfo *info,void *x,Mat J,Mat M,void *ctx), 302f6dfbefdSBarry Smith + info - `DMDALocalInfo` defining the subdomain to evaluate the Jacobian at 3030038884cSBarry Smith . x - dimensional pointer to state at which to evaluate Jacobian (e.g. PetscScalar *x or **x or ***x) 3046b7eb5ceSMatthew G. Knepley . J - Mat object for the Jacobian 3056b7eb5ceSMatthew G. Knepley . M - Mat object for the Jacobian preconditioner matrix 3062961e153SJed Brown - ctx - optional context passed above 3072961e153SJed Brown 3082961e153SJed Brown Level: beginner 3092961e153SJed Brown 310f6dfbefdSBarry Smith .seealso: `DMDA`, `DMDASNESSetFunctionLocal()`, `DMSNESSetJacobian()`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()` 3112961e153SJed Brown @*/ 312d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDASNESSetJacobianLocal(DM dm, PetscErrorCode (*func)(DMDALocalInfo *, void *, Mat, Mat, void *), void *ctx) 313d71ae5a4SJacob Faibussowitsch { 314942e3340SBarry Smith DMSNES sdm; 315942e3340SBarry Smith DMSNES_DA *dmdasnes; 3162961e153SJed Brown 3172961e153SJed Brown PetscFunctionBegin; 3182961e153SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3199566063dSJacob Faibussowitsch PetscCall(DMGetDMSNESWrite(dm, &sdm)); 3209566063dSJacob Faibussowitsch PetscCall(DMDASNESGetContext(dm, sdm, &dmdasnes)); 3211aa26658SKarl Rupp 3222961e153SJed Brown dmdasnes->jacobianlocal = func; 3232961e153SJed Brown dmdasnes->jacobianlocalctx = ctx; 3241aa26658SKarl Rupp 3259566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobian_DMDA, dmdasnes)); 326*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3276cab3a1bSJed Brown } 3282a4ee8f2SPeter Brune 3292a4ee8f2SPeter Brune /*@C 330f6dfbefdSBarry Smith DMDASNESSetJacobianLocalVec - set a local Jacobian evaluation function that operates on a local vector with `DMDA` 3315505f7afSJunchao Zhang 3325505f7afSJunchao Zhang Logically Collective 3335505f7afSJunchao Zhang 3345505f7afSJunchao Zhang Input Parameters: 335f6dfbefdSBarry Smith + dm - `DM` to associate callback with 3365505f7afSJunchao Zhang . func - local Jacobian evaluation 3375505f7afSJunchao Zhang - ctx - optional context for local Jacobian evaluation 3385505f7afSJunchao Zhang 3395505f7afSJunchao Zhang Calling sequence: 3405505f7afSJunchao Zhang For PetscErrorCode (*func)(DMDALocalInfo *info,Vec x,Mat J,Mat M,void *ctx), 341f6dfbefdSBarry Smith + info - `DMDALocalInfo` defining the subdomain to evaluate the Jacobian at 3425505f7afSJunchao Zhang . x - state vector at which to evaluate Jacobian 3435505f7afSJunchao Zhang . J - Mat object for the Jacobian 3445505f7afSJunchao Zhang . M - Mat object for the Jacobian preconditioner matrix 3455505f7afSJunchao Zhang - ctx - optional context passed above 3465505f7afSJunchao Zhang 3475505f7afSJunchao Zhang Level: beginner 3485505f7afSJunchao Zhang 349f6dfbefdSBarry Smith .seealso: `DMDA`, `DMDASNESSetJacobianLocal()`, `DMDASNESSetFunctionLocalVec()`, `DMSNESSetJacobian()`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()` 3505505f7afSJunchao Zhang @*/ 351d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDASNESSetJacobianLocalVec(DM dm, PetscErrorCode (*func)(DMDALocalInfo *, Vec, Mat, Mat, void *), void *ctx) 352d71ae5a4SJacob Faibussowitsch { 3535505f7afSJunchao Zhang DMSNES sdm; 3545505f7afSJunchao Zhang DMSNES_DA *dmdasnes; 3555505f7afSJunchao Zhang 3565505f7afSJunchao Zhang PetscFunctionBegin; 3575505f7afSJunchao Zhang PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3585505f7afSJunchao Zhang PetscCall(DMGetDMSNESWrite(dm, &sdm)); 3595505f7afSJunchao Zhang PetscCall(DMDASNESGetContext(dm, sdm, &dmdasnes)); 3605505f7afSJunchao Zhang 3615505f7afSJunchao Zhang dmdasnes->jacobianlocalvec = func; 3625505f7afSJunchao Zhang dmdasnes->jacobianlocalctx = ctx; 3635505f7afSJunchao Zhang 3645505f7afSJunchao Zhang PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobian_DMDA, dmdasnes)); 365*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3665505f7afSJunchao Zhang } 3675505f7afSJunchao Zhang 3685505f7afSJunchao Zhang /*@C 369f6dfbefdSBarry Smith DMDASNESSetObjectiveLocal - set a local residual evaluation function to used with a `DMDA` 3702a4ee8f2SPeter Brune 3712a4ee8f2SPeter Brune Logically Collective 3722a4ee8f2SPeter Brune 3734165533cSJose E. Roman Input Parameters: 374f6dfbefdSBarry Smith + dm - `DM` to associate callback with 3752a4ee8f2SPeter Brune . func - local objective evaluation 3762a4ee8f2SPeter Brune - ctx - optional context for local residual evaluation 3772a4ee8f2SPeter Brune 3782a4ee8f2SPeter Brune Calling sequence for func: 379f6dfbefdSBarry Smith + info - `DMDALocalInfo` defining the subdomain to evaluate the residual on 3802a4ee8f2SPeter Brune . x - dimensional pointer to state at which to evaluate residual 3812a4ee8f2SPeter Brune . ob - eventual objective value 3822a4ee8f2SPeter Brune - ctx - optional context passed above 3832a4ee8f2SPeter Brune 3842a4ee8f2SPeter Brune Level: beginner 3852a4ee8f2SPeter Brune 386f6dfbefdSBarry Smith .seealso: `DMDA`, `DMSNESSetFunction()`, `DMDASNESSetJacobianLocal()`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()` 3872a4ee8f2SPeter Brune @*/ 388d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDASNESSetObjectiveLocal(DM dm, DMDASNESObjective func, void *ctx) 389d71ae5a4SJacob Faibussowitsch { 390942e3340SBarry Smith DMSNES sdm; 391942e3340SBarry Smith DMSNES_DA *dmdasnes; 3922a4ee8f2SPeter Brune 3932a4ee8f2SPeter Brune PetscFunctionBegin; 3942a4ee8f2SPeter Brune PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3959566063dSJacob Faibussowitsch PetscCall(DMGetDMSNESWrite(dm, &sdm)); 3969566063dSJacob Faibussowitsch PetscCall(DMDASNESGetContext(dm, sdm, &dmdasnes)); 3971aa26658SKarl Rupp 3982a4ee8f2SPeter Brune dmdasnes->objectivelocal = func; 3992a4ee8f2SPeter Brune dmdasnes->objectivelocalctx = ctx; 4001aa26658SKarl Rupp 4019566063dSJacob Faibussowitsch PetscCall(DMSNESSetObjective(dm, SNESComputeObjective_DMDA, dmdasnes)); 402*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4032a4ee8f2SPeter Brune } 404dcad5f1cSBarry Smith 4055505f7afSJunchao Zhang /*@C 406f6dfbefdSBarry Smith DMDASNESSetObjectiveLocal - set a local residual evaluation function that operates on a local vector with `DMDA` 4075505f7afSJunchao Zhang 4085505f7afSJunchao Zhang Logically Collective 4095505f7afSJunchao Zhang 4105505f7afSJunchao Zhang Input Parameters: 411f6dfbefdSBarry Smith + dm - `DM` to associate callback with 4125505f7afSJunchao Zhang . func - local objective evaluation 4135505f7afSJunchao Zhang - ctx - optional context for local residual evaluation 4145505f7afSJunchao Zhang 4155505f7afSJunchao Zhang Calling sequence 4165505f7afSJunchao Zhang For PetscErrorCode (*func)(DMDALocalInfo *info,Vec x,PetscReal *ob,void *ctx); 417f6dfbefdSBarry Smith + info - `DMDALocalInfo` defining the subdomain to evaluate the residual on 4185505f7afSJunchao Zhang . x - state vector at which to evaluate residual 4195505f7afSJunchao Zhang . ob - eventual objective value 4205505f7afSJunchao Zhang - ctx - optional context passed above 4215505f7afSJunchao Zhang 4225505f7afSJunchao Zhang Level: beginner 4235505f7afSJunchao Zhang 424f6dfbefdSBarry Smith .seealso: `DMDA`, `DMDASNESSetObjectiveLocal()`, `DMSNESSetFunction()`, `DMDASNESSetJacobianLocalVec()`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()` 4255505f7afSJunchao Zhang @*/ 426d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDASNESSetObjectiveLocalVec(DM dm, DMDASNESObjectiveVec func, void *ctx) 427d71ae5a4SJacob Faibussowitsch { 4285505f7afSJunchao Zhang DMSNES sdm; 4295505f7afSJunchao Zhang DMSNES_DA *dmdasnes; 4305505f7afSJunchao Zhang 4315505f7afSJunchao Zhang PetscFunctionBegin; 4325505f7afSJunchao Zhang PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4335505f7afSJunchao Zhang PetscCall(DMGetDMSNESWrite(dm, &sdm)); 4345505f7afSJunchao Zhang PetscCall(DMDASNESGetContext(dm, sdm, &dmdasnes)); 4355505f7afSJunchao Zhang 4365505f7afSJunchao Zhang dmdasnes->objectivelocalvec = func; 4375505f7afSJunchao Zhang dmdasnes->objectivelocalctx = ctx; 4385505f7afSJunchao Zhang 4395505f7afSJunchao Zhang PetscCall(DMSNESSetObjective(dm, SNESComputeObjective_DMDA, dmdasnes)); 440*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4415505f7afSJunchao Zhang } 4425505f7afSJunchao Zhang 443d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESComputePicard_DMDA(SNES snes, Vec X, Vec F, void *ctx) 444d71ae5a4SJacob Faibussowitsch { 445dcad5f1cSBarry Smith DM dm; 446942e3340SBarry Smith DMSNES_DA *dmdasnes = (DMSNES_DA *)ctx; 447dcad5f1cSBarry Smith DMDALocalInfo info; 448dcad5f1cSBarry Smith Vec Xloc; 449dcad5f1cSBarry Smith void *x, *f; 450dcad5f1cSBarry Smith 451dcad5f1cSBarry Smith PetscFunctionBegin; 452dcad5f1cSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 453dcad5f1cSBarry Smith PetscValidHeaderSpecific(X, VEC_CLASSID, 2); 454dcad5f1cSBarry Smith PetscValidHeaderSpecific(F, VEC_CLASSID, 3); 45528b400f6SJacob Faibussowitsch PetscCheck(dmdasnes->rhsplocal, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "Corrupt context"); 4569566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 4579566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &Xloc)); 4589566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, X, INSERT_VALUES, Xloc)); 4599566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, X, INSERT_VALUES, Xloc)); 4609566063dSJacob Faibussowitsch PetscCall(DMDAGetLocalInfo(dm, &info)); 4619566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(dm, Xloc, &x)); 462dcad5f1cSBarry Smith switch (dmdasnes->residuallocalimode) { 463dcad5f1cSBarry Smith case INSERT_VALUES: { 4649566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(dm, F, &f)); 465792fecdfSBarry Smith PetscCallBack("SNES Picard DMDA local callback function", (*dmdasnes->rhsplocal)(&info, x, f, dmdasnes->picardlocalctx)); 4669566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(dm, F, &f)); 467dcad5f1cSBarry Smith } break; 468dcad5f1cSBarry Smith case ADD_VALUES: { 469dcad5f1cSBarry Smith Vec Floc; 4709566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &Floc)); 4719566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Floc)); 4729566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(dm, Floc, &f)); 473792fecdfSBarry Smith PetscCallBack("SNES Picard DMDA local callback function", (*dmdasnes->rhsplocal)(&info, x, f, dmdasnes->picardlocalctx)); 4749566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(dm, Floc, &f)); 4759566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(F)); 4769566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dm, Floc, ADD_VALUES, F)); 4779566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dm, Floc, ADD_VALUES, F)); 4789566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &Floc)); 479dcad5f1cSBarry Smith } break; 480d71ae5a4SJacob Faibussowitsch default: 481d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "Cannot use imode=%d", (int)dmdasnes->residuallocalimode); 482dcad5f1cSBarry Smith } 4839566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(dm, Xloc, &x)); 4849566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &Xloc)); 485*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 486dcad5f1cSBarry Smith } 487dcad5f1cSBarry Smith 488d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESComputePicardJacobian_DMDA(SNES snes, Vec X, Mat A, Mat B, void *ctx) 489d71ae5a4SJacob Faibussowitsch { 490dcad5f1cSBarry Smith DM dm; 491942e3340SBarry Smith DMSNES_DA *dmdasnes = (DMSNES_DA *)ctx; 492dcad5f1cSBarry Smith DMDALocalInfo info; 493dcad5f1cSBarry Smith Vec Xloc; 494dcad5f1cSBarry Smith void *x; 495dcad5f1cSBarry Smith 496dcad5f1cSBarry Smith PetscFunctionBegin; 49728b400f6SJacob Faibussowitsch PetscCheck(dmdasnes->jacobianplocal, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "Corrupt context"); 4989566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 499dcad5f1cSBarry Smith 5009566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &Xloc)); 5019566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, X, INSERT_VALUES, Xloc)); 5029566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, X, INSERT_VALUES, Xloc)); 5039566063dSJacob Faibussowitsch PetscCall(DMDAGetLocalInfo(dm, &info)); 5049566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(dm, Xloc, &x)); 505792fecdfSBarry Smith PetscCallBack("SNES Picard DMDA local callback Jacobian", (*dmdasnes->jacobianplocal)(&info, x, A, B, dmdasnes->picardlocalctx)); 5069566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(dm, Xloc, &x)); 5079566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &Xloc)); 50894ab13aaSBarry Smith if (A != B) { 5099566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 5109566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 511dcad5f1cSBarry Smith } 512*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 513dcad5f1cSBarry Smith } 514dcad5f1cSBarry Smith 515dcad5f1cSBarry Smith /*@C 516f6dfbefdSBarry Smith DMDASNESSetPicardLocal - set a local right hand side and matrix evaluation function for Picard iteration with `DMDA` 517dcad5f1cSBarry Smith 518dcad5f1cSBarry Smith Logically Collective 519dcad5f1cSBarry Smith 5204165533cSJose E. Roman Input Parameters: 521f6dfbefdSBarry Smith + dm - `DM` to associate callback with 522f6dfbefdSBarry Smith . imode - `INSERT_VALUES` if local function computes owned part, `ADD_VALUES` if it contributes to ghosted part 523dcad5f1cSBarry Smith . func - local residual evaluation 524dcad5f1cSBarry Smith - ctx - optional context for local residual evaluation 525dcad5f1cSBarry Smith 526dcad5f1cSBarry Smith Calling sequence for func: 527f6dfbefdSBarry Smith + info - `DMDALocalInfo` defining the subdomain to evaluate the residual on 528dcad5f1cSBarry Smith . x - dimensional pointer to state at which to evaluate residual 529dcad5f1cSBarry Smith . f - dimensional pointer to residual, write the residual here 530dcad5f1cSBarry Smith - ctx - optional context passed above 531dcad5f1cSBarry Smith 532f6dfbefdSBarry Smith Note: 533f6dfbefdSBarry Smith The user must use `SNESSetFunction`(snes,NULL,`SNESPicardComputeFunction`,&user)); 534dcad5f1cSBarry Smith in their code before calling this routine. 535dcad5f1cSBarry Smith 536dcad5f1cSBarry Smith Level: beginner 537dcad5f1cSBarry Smith 538f6dfbefdSBarry Smith .seealso: `DMDA`, `DMSNESSetFunction()`, `DMDASNESSetJacobian()`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()` 539dcad5f1cSBarry Smith @*/ 540d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDASNESSetPicardLocal(DM dm, InsertMode imode, PetscErrorCode (*func)(DMDALocalInfo *, void *, void *, void *), PetscErrorCode (*jac)(DMDALocalInfo *, void *, Mat, Mat, void *), void *ctx) 541d71ae5a4SJacob Faibussowitsch { 542942e3340SBarry Smith DMSNES sdm; 543942e3340SBarry Smith DMSNES_DA *dmdasnes; 544dcad5f1cSBarry Smith 545dcad5f1cSBarry Smith PetscFunctionBegin; 546dcad5f1cSBarry Smith PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5479566063dSJacob Faibussowitsch PetscCall(DMGetDMSNESWrite(dm, &sdm)); 5489566063dSJacob Faibussowitsch PetscCall(DMDASNESGetContext(dm, sdm, &dmdasnes)); 5491aa26658SKarl Rupp 550dcad5f1cSBarry Smith dmdasnes->residuallocalimode = imode; 551dcad5f1cSBarry Smith dmdasnes->rhsplocal = func; 552dcad5f1cSBarry Smith dmdasnes->jacobianplocal = jac; 553dcad5f1cSBarry Smith dmdasnes->picardlocalctx = ctx; 5541aa26658SKarl Rupp 5559566063dSJacob Faibussowitsch PetscCall(DMSNESSetPicard(dm, SNESComputePicard_DMDA, SNESComputePicardJacobian_DMDA, dmdasnes)); 5569566063dSJacob Faibussowitsch PetscCall(DMSNESSetMFFunction(dm, SNESComputeFunction_DMDA, dmdasnes)); 557*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 558dcad5f1cSBarry Smith } 559