1af0996ceSBarry Smith #include <petsc/private/dmimpl.h> 2af0996ceSBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/ 3ff35dfedSBarry Smith 4ff35dfedSBarry Smith typedef struct { 5ff35dfedSBarry Smith PetscErrorCode (*residuallocal)(DM,Vec,Vec,void*); 6d1e9a80fSBarry Smith PetscErrorCode (*jacobianlocal)(DM,Vec,Mat,Mat,void*); 7bdd6f66aSToby Isaac PetscErrorCode (*boundarylocal)(DM,Vec,void*); 8ff35dfedSBarry Smith void *residuallocalctx; 9ff35dfedSBarry Smith void *jacobianlocalctx; 10bdd6f66aSToby Isaac void *boundarylocalctx; 11942e3340SBarry Smith } DMSNES_Local; 12ff35dfedSBarry Smith 13942e3340SBarry Smith static PetscErrorCode DMSNESDestroy_DMLocal(DMSNES sdm) 14ff35dfedSBarry Smith { 15ff35dfedSBarry Smith PetscErrorCode ierr; 16ff35dfedSBarry Smith 17ff35dfedSBarry Smith PetscFunctionBegin; 18ff35dfedSBarry Smith ierr = PetscFree(sdm->data);CHKERRQ(ierr); 19ff35dfedSBarry Smith PetscFunctionReturn(0); 20ff35dfedSBarry Smith } 21ff35dfedSBarry Smith 2222c6f798SBarry Smith static PetscErrorCode DMSNESDuplicate_DMLocal(DMSNES oldsdm,DMSNES sdm) 23ff35dfedSBarry Smith { 24ff35dfedSBarry Smith PetscErrorCode ierr; 25ff35dfedSBarry Smith 26ff35dfedSBarry Smith PetscFunctionBegin; 27b00a9115SJed Brown ierr = PetscNewLog(sdm,(DMSNES_Local**)&sdm->data);CHKERRQ(ierr); 28ff35dfedSBarry Smith if (oldsdm->data) { 29942e3340SBarry Smith ierr = PetscMemcpy(sdm->data,oldsdm->data,sizeof(DMSNES_Local));CHKERRQ(ierr); 30ff35dfedSBarry Smith } 31ff35dfedSBarry Smith PetscFunctionReturn(0); 32ff35dfedSBarry Smith } 33ff35dfedSBarry Smith 34942e3340SBarry Smith static PetscErrorCode DMLocalSNESGetContext(DM dm,DMSNES sdm,DMSNES_Local **dmlocalsnes) 35ff35dfedSBarry Smith { 36ff35dfedSBarry Smith PetscErrorCode ierr; 37ff35dfedSBarry Smith 38ff35dfedSBarry Smith PetscFunctionBegin; 390298fd71SBarry Smith *dmlocalsnes = NULL; 40ff35dfedSBarry Smith if (!sdm->data) { 41b00a9115SJed Brown ierr = PetscNewLog(dm,(DMSNES_Local**)&sdm->data);CHKERRQ(ierr); 421aa26658SKarl Rupp 4322c6f798SBarry Smith sdm->ops->destroy = DMSNESDestroy_DMLocal; 4422c6f798SBarry Smith sdm->ops->duplicate = DMSNESDuplicate_DMLocal; 45ff35dfedSBarry Smith } 46942e3340SBarry Smith *dmlocalsnes = (DMSNES_Local*)sdm->data; 47ff35dfedSBarry Smith PetscFunctionReturn(0); 48ff35dfedSBarry Smith } 49ff35dfedSBarry Smith 50b2270762SBarry Smith static PetscErrorCode SNESComputeFunction_DMLocal(SNES snes,Vec X,Vec F,void *ctx) 51ff35dfedSBarry Smith { 52ff35dfedSBarry Smith PetscErrorCode ierr; 53ff35dfedSBarry Smith DM dm; 54942e3340SBarry Smith DMSNES_Local *dmlocalsnes = (DMSNES_Local*)ctx; 55ff35dfedSBarry Smith Vec Xloc,Floc; 56ff35dfedSBarry Smith 57ff35dfedSBarry Smith PetscFunctionBegin; 58ff35dfedSBarry Smith PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 59ff35dfedSBarry Smith PetscValidHeaderSpecific(X,VEC_CLASSID,2); 60ff35dfedSBarry Smith PetscValidHeaderSpecific(F,VEC_CLASSID,3); 61ff35dfedSBarry Smith ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 62ff35dfedSBarry Smith ierr = DMGetLocalVector(dm,&Xloc);CHKERRQ(ierr); 63ff35dfedSBarry Smith ierr = DMGetLocalVector(dm,&Floc);CHKERRQ(ierr); 64ff35dfedSBarry Smith ierr = VecZeroEntries(Xloc);CHKERRQ(ierr); 65bdd6f66aSToby Isaac if (dmlocalsnes->boundarylocal) {ierr = (*dmlocalsnes->boundarylocal)(dm,Xloc,dmlocalsnes->boundarylocalctx);CHKERRQ(ierr);} 66ff35dfedSBarry Smith ierr = VecZeroEntries(Floc);CHKERRQ(ierr); 67ff35dfedSBarry Smith ierr = DMGlobalToLocalBegin(dm,X,INSERT_VALUES,Xloc);CHKERRQ(ierr); 68ff35dfedSBarry Smith ierr = DMGlobalToLocalEnd(dm,X,INSERT_VALUES,Xloc);CHKERRQ(ierr); 69ff35dfedSBarry Smith CHKMEMQ; 70ff35dfedSBarry Smith ierr = (*dmlocalsnes->residuallocal)(dm,Xloc,Floc,dmlocalsnes->residuallocalctx);CHKERRQ(ierr); 71ff35dfedSBarry Smith CHKMEMQ; 72ff35dfedSBarry Smith ierr = VecZeroEntries(F);CHKERRQ(ierr); 73ff35dfedSBarry Smith ierr = DMLocalToGlobalBegin(dm,Floc,ADD_VALUES,F);CHKERRQ(ierr); 74ff35dfedSBarry Smith ierr = DMLocalToGlobalEnd(dm,Floc,ADD_VALUES,F);CHKERRQ(ierr); 75ff35dfedSBarry Smith ierr = DMRestoreLocalVector(dm,&Floc);CHKERRQ(ierr); 76ff35dfedSBarry Smith ierr = DMRestoreLocalVector(dm,&Xloc);CHKERRQ(ierr); 77afa9dec6SMatthew G. Knepley { 78afa9dec6SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 79afa9dec6SMatthew G. Knepley PetscInt it; 80afa9dec6SMatthew G. Knepley 81afa9dec6SMatthew G. Knepley ierr = SNESGetIterationNumber(snes, &it);CHKERRQ(ierr); 82afa9dec6SMatthew G. Knepley ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN, "Solution, Iterate %d", (int) it);CHKERRQ(ierr); 83afa9dec6SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) X, name);CHKERRQ(ierr); 84*85997439SMatthew G. Knepley ierr = VecViewFromOptions(X, (PetscObject) snes, "-dmsnes_solution_vec_view");CHKERRQ(ierr); 85afa9dec6SMatthew G. Knepley ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN, "Residual, Iterate %d", (int) it);CHKERRQ(ierr); 86afa9dec6SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) F, name);CHKERRQ(ierr); 87*85997439SMatthew G. Knepley ierr = VecViewFromOptions(F, (PetscObject) snes, "-dmsnes_residual_vec_view");CHKERRQ(ierr); 88afa9dec6SMatthew G. Knepley } 89ff35dfedSBarry Smith PetscFunctionReturn(0); 90ff35dfedSBarry Smith } 91ff35dfedSBarry Smith 92d1e9a80fSBarry Smith static PetscErrorCode SNESComputeJacobian_DMLocal(SNES snes,Vec X,Mat A,Mat B,void *ctx) 93ff35dfedSBarry Smith { 94ff35dfedSBarry Smith PetscErrorCode ierr; 95ff35dfedSBarry Smith DM dm; 96942e3340SBarry Smith DMSNES_Local *dmlocalsnes = (DMSNES_Local*)ctx; 97ff35dfedSBarry Smith Vec Xloc; 98ff35dfedSBarry Smith 99ff35dfedSBarry Smith PetscFunctionBegin; 100ff35dfedSBarry Smith ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 101ff35dfedSBarry Smith if (dmlocalsnes->jacobianlocal) { 102ff35dfedSBarry Smith ierr = DMGetLocalVector(dm,&Xloc);CHKERRQ(ierr); 103ff35dfedSBarry Smith ierr = VecZeroEntries(Xloc);CHKERRQ(ierr); 104bdd6f66aSToby Isaac if (dmlocalsnes->boundarylocal) {ierr = (*dmlocalsnes->boundarylocal)(dm,Xloc,dmlocalsnes->boundarylocalctx);CHKERRQ(ierr);} 105ff35dfedSBarry Smith ierr = DMGlobalToLocalBegin(dm,X,INSERT_VALUES,Xloc);CHKERRQ(ierr); 106ff35dfedSBarry Smith ierr = DMGlobalToLocalEnd(dm,X,INSERT_VALUES,Xloc);CHKERRQ(ierr); 107ff35dfedSBarry Smith CHKMEMQ; 108d1e9a80fSBarry Smith ierr = (*dmlocalsnes->jacobianlocal)(dm,Xloc,A,B,dmlocalsnes->jacobianlocalctx);CHKERRQ(ierr); 109ff35dfedSBarry Smith CHKMEMQ; 110ff35dfedSBarry Smith ierr = DMRestoreLocalVector(dm,&Xloc);CHKERRQ(ierr); 111ff35dfedSBarry Smith } else { 112ff35dfedSBarry Smith MatFDColoring fdcoloring; 113ff35dfedSBarry Smith ierr = PetscObjectQuery((PetscObject)dm,"DMDASNES_FDCOLORING",(PetscObject*)&fdcoloring);CHKERRQ(ierr); 114ff35dfedSBarry Smith if (!fdcoloring) { 115ff35dfedSBarry Smith ISColoring coloring; 116ff35dfedSBarry Smith 117b412c318SBarry Smith ierr = DMCreateColoring(dm,dm->coloringtype,&coloring);CHKERRQ(ierr); 11894ab13aaSBarry Smith ierr = MatFDColoringCreate(B,coloring,&fdcoloring);CHKERRQ(ierr); 119ff35dfedSBarry Smith ierr = ISColoringDestroy(&coloring);CHKERRQ(ierr); 120ff35dfedSBarry Smith switch (dm->coloringtype) { 121ff35dfedSBarry Smith case IS_COLORING_GLOBAL: 122ff35dfedSBarry Smith ierr = MatFDColoringSetFunction(fdcoloring,(PetscErrorCode (*)(void))SNESComputeFunction_DMLocal,dmlocalsnes);CHKERRQ(ierr); 123ff35dfedSBarry Smith break; 124ce94432eSBarry Smith default: SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_SUP,"No support for coloring type '%s'",ISColoringTypes[dm->coloringtype]); 125ff35dfedSBarry Smith } 126ff35dfedSBarry Smith ierr = PetscObjectSetOptionsPrefix((PetscObject)fdcoloring,((PetscObject)dm)->prefix);CHKERRQ(ierr); 127ff35dfedSBarry Smith ierr = MatFDColoringSetFromOptions(fdcoloring);CHKERRQ(ierr); 12894ab13aaSBarry Smith ierr = MatFDColoringSetUp(B,coloring,fdcoloring);CHKERRQ(ierr); 129ff35dfedSBarry Smith ierr = PetscObjectCompose((PetscObject)dm,"DMDASNES_FDCOLORING",(PetscObject)fdcoloring);CHKERRQ(ierr); 130ff35dfedSBarry Smith ierr = PetscObjectDereference((PetscObject)fdcoloring);CHKERRQ(ierr); 131ff35dfedSBarry Smith 132ff35dfedSBarry Smith /* The following breaks an ugly reference counting loop that deserves a paragraph. MatFDColoringApply() will call 133ff35dfedSBarry Smith * VecDuplicate() with the state Vec and store inside the MatFDColoring. This Vec will duplicate the Vec, but the 134ff35dfedSBarry Smith * MatFDColoring is composed with the DM. We dereference the DM here so that the reference count will eventually 135ff35dfedSBarry Smith * drop to 0. Note the code in DMDestroy() that exits early for a negative reference count. That code path will be 136140e18c1SBarry Smith * taken when the PetscObjectList for the Vec inside MatFDColoring is destroyed. 137ff35dfedSBarry Smith */ 138ff35dfedSBarry Smith ierr = PetscObjectDereference((PetscObject)dm);CHKERRQ(ierr); 139ff35dfedSBarry Smith } 140d1e9a80fSBarry Smith ierr = MatFDColoringApply(B,fdcoloring,X,snes);CHKERRQ(ierr); 141ff35dfedSBarry Smith } 142ff35dfedSBarry Smith /* This will be redundant if the user called both, but it's too common to forget. */ 14394ab13aaSBarry Smith if (A != B) { 14494ab13aaSBarry Smith ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 14594ab13aaSBarry Smith ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 146ff35dfedSBarry Smith } 147ff35dfedSBarry Smith PetscFunctionReturn(0); 148ff35dfedSBarry Smith } 149ff35dfedSBarry Smith 150ff35dfedSBarry Smith /*@C 151ff35dfedSBarry Smith DMSNESSetFunctionLocal - set a local residual evaluation function. This function is called with local vector 152ff35dfedSBarry Smith containing the local vector information PLUS ghost point information. It should compute a result for all local 153ff35dfedSBarry Smith elements and DMSNES will automatically accumulate the overlapping values. 154ff35dfedSBarry Smith 155ff35dfedSBarry Smith Logically Collective 156ff35dfedSBarry Smith 157ff35dfedSBarry Smith Input Arguments: 158ff35dfedSBarry Smith + dm - DM to associate callback with 159ff35dfedSBarry Smith . func - local residual evaluation 160ff35dfedSBarry Smith - ctx - optional context for local residual evaluation 161ff35dfedSBarry Smith 162ff35dfedSBarry Smith Level: beginner 163ff35dfedSBarry Smith 164ff35dfedSBarry Smith .seealso: DMSNESSetFunction(), DMDASNESSetJacobianLocal(), DMDACreate1d(), DMDACreate2d(), DMDACreate3d() 165ff35dfedSBarry Smith @*/ 166ff35dfedSBarry Smith PetscErrorCode DMSNESSetFunctionLocal(DM dm,PetscErrorCode (*func)(DM,Vec,Vec,void*),void *ctx) 167ff35dfedSBarry Smith { 168ff35dfedSBarry Smith PetscErrorCode ierr; 169942e3340SBarry Smith DMSNES sdm; 170942e3340SBarry Smith DMSNES_Local *dmlocalsnes; 171ff35dfedSBarry Smith 172ff35dfedSBarry Smith PetscFunctionBegin; 173ff35dfedSBarry Smith PetscValidHeaderSpecific(dm,DM_CLASSID,1); 174942e3340SBarry Smith ierr = DMGetDMSNESWrite(dm,&sdm);CHKERRQ(ierr); 175ff35dfedSBarry Smith ierr = DMLocalSNESGetContext(dm,sdm,&dmlocalsnes);CHKERRQ(ierr); 1761aa26658SKarl Rupp 177ff35dfedSBarry Smith dmlocalsnes->residuallocal = func; 178ff35dfedSBarry Smith dmlocalsnes->residuallocalctx = ctx; 1791aa26658SKarl Rupp 180ff35dfedSBarry Smith ierr = DMSNESSetFunction(dm,SNESComputeFunction_DMLocal,dmlocalsnes);CHKERRQ(ierr); 18122c6f798SBarry Smith if (!sdm->ops->computejacobian) { /* Call us for the Jacobian too, can be overridden by the user. */ 182ff35dfedSBarry Smith ierr = DMSNESSetJacobian(dm,SNESComputeJacobian_DMLocal,dmlocalsnes);CHKERRQ(ierr); 183ff35dfedSBarry Smith } 184ff35dfedSBarry Smith PetscFunctionReturn(0); 185ff35dfedSBarry Smith } 186ff35dfedSBarry Smith 187bdd6f66aSToby Isaac /*@C 188bdd6f66aSToby Isaac DMSNESSetBoundaryLocal - set a local boundary value function. This function is called with local vector 189bdd6f66aSToby Isaac containing the local vector information PLUS ghost point information. It should insert values into the local 190bdd6f66aSToby Isaac vector that do not come from the global vector, such as essential boundary condition data. 191bdd6f66aSToby Isaac 192bdd6f66aSToby Isaac Logically Collective 193bdd6f66aSToby Isaac 194bdd6f66aSToby Isaac Input Arguments: 195bdd6f66aSToby Isaac + dm - DM to associate callback with 196bdd6f66aSToby Isaac . func - local boundary value evaluation 197bdd6f66aSToby Isaac - ctx - optional context for local boundary value evaluation 198bdd6f66aSToby Isaac 199bdd6f66aSToby Isaac Level: intermediate 200bdd6f66aSToby Isaac 201bdd6f66aSToby Isaac .seealso: DMSNESSetFunctionLocal(), DMDASNESSetJacobianLocal() 202bdd6f66aSToby Isaac @*/ 203bdd6f66aSToby Isaac PetscErrorCode DMSNESSetBoundaryLocal(DM dm,PetscErrorCode (*func)(DM,Vec,void*),void *ctx) 204bdd6f66aSToby Isaac { 205bdd6f66aSToby Isaac PetscErrorCode ierr; 206bdd6f66aSToby Isaac DMSNES sdm; 207bdd6f66aSToby Isaac DMSNES_Local *dmlocalsnes; 208bdd6f66aSToby Isaac 209bdd6f66aSToby Isaac PetscFunctionBegin; 210bdd6f66aSToby Isaac PetscValidHeaderSpecific(dm,DM_CLASSID,1); 211bdd6f66aSToby Isaac ierr = DMGetDMSNESWrite(dm,&sdm);CHKERRQ(ierr); 212bdd6f66aSToby Isaac ierr = DMLocalSNESGetContext(dm,sdm,&dmlocalsnes);CHKERRQ(ierr); 213bdd6f66aSToby Isaac 214bdd6f66aSToby Isaac dmlocalsnes->boundarylocal = func; 215bdd6f66aSToby Isaac dmlocalsnes->boundarylocalctx = ctx; 216bdd6f66aSToby Isaac 217bdd6f66aSToby Isaac PetscFunctionReturn(0); 218bdd6f66aSToby Isaac } 219bdd6f66aSToby Isaac 220ff35dfedSBarry Smith /*@C 221ff35dfedSBarry Smith DMSNESSetJacobianLocal - set a local Jacobian evaluation function 222ff35dfedSBarry Smith 223ff35dfedSBarry Smith Logically Collective 224ff35dfedSBarry Smith 225ff35dfedSBarry Smith Input Arguments: 226ff35dfedSBarry Smith + dm - DM to associate callback with 227ff35dfedSBarry Smith . func - local Jacobian evaluation 228ff35dfedSBarry Smith - ctx - optional context for local Jacobian evaluation 229ff35dfedSBarry Smith 230ff35dfedSBarry Smith Level: beginner 231ff35dfedSBarry Smith 232ff35dfedSBarry Smith .seealso: DMSNESSetJacobian(), DMDASNESSetJacobian(), DMDACreate1d(), DMDACreate2d(), DMDACreate3d() 233ff35dfedSBarry Smith @*/ 234d1e9a80fSBarry Smith PetscErrorCode DMSNESSetJacobianLocal(DM dm,PetscErrorCode (*func)(DM,Vec,Mat,Mat,void*),void *ctx) 235ff35dfedSBarry Smith { 236ff35dfedSBarry Smith PetscErrorCode ierr; 237942e3340SBarry Smith DMSNES sdm; 238942e3340SBarry Smith DMSNES_Local *dmlocalsnes; 239ff35dfedSBarry Smith 240ff35dfedSBarry Smith PetscFunctionBegin; 241ff35dfedSBarry Smith PetscValidHeaderSpecific(dm,DM_CLASSID,1); 242942e3340SBarry Smith ierr = DMGetDMSNESWrite(dm,&sdm);CHKERRQ(ierr); 243ff35dfedSBarry Smith ierr = DMLocalSNESGetContext(dm,sdm,&dmlocalsnes);CHKERRQ(ierr); 2441aa26658SKarl Rupp 245ff35dfedSBarry Smith dmlocalsnes->jacobianlocal = func; 246ff35dfedSBarry Smith dmlocalsnes->jacobianlocalctx = ctx; 2471aa26658SKarl Rupp 248ff35dfedSBarry Smith ierr = DMSNESSetJacobian(dm,SNESComputeJacobian_DMLocal,dmlocalsnes);CHKERRQ(ierr); 249ff35dfedSBarry Smith PetscFunctionReturn(0); 250ff35dfedSBarry Smith } 251ff35dfedSBarry Smith 252