1*ff35dfedSBarry Smith #include <petsc-private/dmimpl.h> 2*ff35dfedSBarry Smith #include <petsc-private/snesimpl.h> /*I "petscsnes.h" I*/ 3*ff35dfedSBarry Smith 4*ff35dfedSBarry Smith typedef struct { 5*ff35dfedSBarry Smith PetscErrorCode (*residuallocal)(DM,Vec,Vec,void*); 6*ff35dfedSBarry Smith PetscErrorCode (*jacobianlocal)(DM,Vec,Mat,Mat,MatStructure*,void*); 7*ff35dfedSBarry Smith void *residuallocalctx; 8*ff35dfedSBarry Smith void *jacobianlocalctx; 9*ff35dfedSBarry Smith } DMLocal_SNES; 10*ff35dfedSBarry Smith 11*ff35dfedSBarry Smith #undef __FUNCT__ 12*ff35dfedSBarry Smith #define __FUNCT__ "SNESDMDestroy_DMLocal" 13*ff35dfedSBarry Smith static PetscErrorCode SNESDMDestroy_DMLocal(SNESDM sdm) 14*ff35dfedSBarry Smith { 15*ff35dfedSBarry Smith PetscErrorCode ierr; 16*ff35dfedSBarry Smith 17*ff35dfedSBarry Smith PetscFunctionBegin; 18*ff35dfedSBarry Smith ierr = PetscFree(sdm->data);CHKERRQ(ierr); 19*ff35dfedSBarry Smith PetscFunctionReturn(0); 20*ff35dfedSBarry Smith } 21*ff35dfedSBarry Smith 22*ff35dfedSBarry Smith #undef __FUNCT__ 23*ff35dfedSBarry Smith #define __FUNCT__ "SNESDMDuplicate_DMLocal" 24*ff35dfedSBarry Smith static PetscErrorCode SNESDMDuplicate_DMLocal(SNESDM oldsdm,DM dm) 25*ff35dfedSBarry Smith { 26*ff35dfedSBarry Smith PetscErrorCode ierr; 27*ff35dfedSBarry Smith SNESDM sdm; 28*ff35dfedSBarry Smith 29*ff35dfedSBarry Smith PetscFunctionBegin; 30*ff35dfedSBarry Smith ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr); 31*ff35dfedSBarry Smith ierr = PetscNewLog(dm,DMLocal_SNES,&sdm->data);CHKERRQ(ierr); 32*ff35dfedSBarry Smith if (oldsdm->data) { 33*ff35dfedSBarry Smith ierr = PetscMemcpy(sdm->data,oldsdm->data,sizeof(DMLocal_SNES));CHKERRQ(ierr); 34*ff35dfedSBarry Smith } 35*ff35dfedSBarry Smith PetscFunctionReturn(0); 36*ff35dfedSBarry Smith } 37*ff35dfedSBarry Smith 38*ff35dfedSBarry Smith #undef __FUNCT__ 39*ff35dfedSBarry Smith #define __FUNCT__ "DMLocalSNESGetContext" 40*ff35dfedSBarry Smith static PetscErrorCode DMLocalSNESGetContext(DM dm,SNESDM sdm,DMLocal_SNES **dmlocalsnes) 41*ff35dfedSBarry Smith { 42*ff35dfedSBarry Smith PetscErrorCode ierr; 43*ff35dfedSBarry Smith 44*ff35dfedSBarry Smith PetscFunctionBegin; 45*ff35dfedSBarry Smith *dmlocalsnes = PETSC_NULL; 46*ff35dfedSBarry Smith if (!sdm->data) { 47*ff35dfedSBarry Smith ierr = PetscNewLog(dm,DMLocal_SNES,&sdm->data);CHKERRQ(ierr); 48*ff35dfedSBarry Smith sdm->destroy = SNESDMDestroy_DMLocal; 49*ff35dfedSBarry Smith sdm->duplicate = SNESDMDuplicate_DMLocal; 50*ff35dfedSBarry Smith } 51*ff35dfedSBarry Smith *dmlocalsnes = (DMLocal_SNES*)sdm->data; 52*ff35dfedSBarry Smith PetscFunctionReturn(0); 53*ff35dfedSBarry Smith } 54*ff35dfedSBarry Smith 55*ff35dfedSBarry Smith #undef __FUNCT__ 56*ff35dfedSBarry Smith #define __FUNCT__ "SNESComputeFunction_DMLocal" 57*ff35dfedSBarry Smith PetscErrorCode SNESComputeFunction_DMLocal(SNES snes,Vec X,Vec F,void *ctx) 58*ff35dfedSBarry Smith { 59*ff35dfedSBarry Smith PetscErrorCode ierr; 60*ff35dfedSBarry Smith DM dm; 61*ff35dfedSBarry Smith DMLocal_SNES *dmlocalsnes = (DMLocal_SNES*)ctx; 62*ff35dfedSBarry Smith Vec Xloc,Floc; 63*ff35dfedSBarry Smith 64*ff35dfedSBarry Smith PetscFunctionBegin; 65*ff35dfedSBarry Smith PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 66*ff35dfedSBarry Smith PetscValidHeaderSpecific(X,VEC_CLASSID,2); 67*ff35dfedSBarry Smith PetscValidHeaderSpecific(F,VEC_CLASSID,3); 68*ff35dfedSBarry Smith ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 69*ff35dfedSBarry Smith ierr = DMGetLocalVector(dm,&Xloc);CHKERRQ(ierr); 70*ff35dfedSBarry Smith ierr = DMGetLocalVector(dm,&Floc);CHKERRQ(ierr); 71*ff35dfedSBarry Smith ierr = VecZeroEntries(Xloc);CHKERRQ(ierr); 72*ff35dfedSBarry Smith ierr = VecZeroEntries(Floc);CHKERRQ(ierr); 73*ff35dfedSBarry Smith ierr = DMGlobalToLocalBegin(dm,X,INSERT_VALUES,Xloc);CHKERRQ(ierr); 74*ff35dfedSBarry Smith ierr = DMGlobalToLocalEnd(dm,X,INSERT_VALUES,Xloc);CHKERRQ(ierr); 75*ff35dfedSBarry Smith printf("x ---------------------\n"); 76*ff35dfedSBarry Smith VecView(X,0); 77*ff35dfedSBarry Smith printf("localx --------------------\n"); 78*ff35dfedSBarry Smith VecView(Xloc,0); 79*ff35dfedSBarry Smith CHKMEMQ; 80*ff35dfedSBarry Smith ierr = (*dmlocalsnes->residuallocal)(dm,Xloc,Floc,dmlocalsnes->residuallocalctx);CHKERRQ(ierr); 81*ff35dfedSBarry Smith CHKMEMQ; 82*ff35dfedSBarry Smith printf("localf ------------------\n"); 83*ff35dfedSBarry Smith VecView(Floc,0); 84*ff35dfedSBarry Smith ierr = VecZeroEntries(F);CHKERRQ(ierr); 85*ff35dfedSBarry Smith ierr = DMLocalToGlobalBegin(dm,Floc,ADD_VALUES,F);CHKERRQ(ierr); 86*ff35dfedSBarry Smith ierr = DMLocalToGlobalEnd(dm,Floc,ADD_VALUES,F);CHKERRQ(ierr); 87*ff35dfedSBarry Smith printf("f-----------------------\n"); 88*ff35dfedSBarry Smith VecView(F,0); 89*ff35dfedSBarry Smith ierr = DMRestoreLocalVector(dm,&Floc);CHKERRQ(ierr); 90*ff35dfedSBarry Smith ierr = DMRestoreLocalVector(dm,&Xloc);CHKERRQ(ierr); 91*ff35dfedSBarry Smith PetscFunctionReturn(0); 92*ff35dfedSBarry Smith } 93*ff35dfedSBarry Smith 94*ff35dfedSBarry Smith #undef __FUNCT__ 95*ff35dfedSBarry Smith #define __FUNCT__ "SNESComputeJacobian_DMLocal" 96*ff35dfedSBarry Smith static PetscErrorCode SNESComputeJacobian_DMLocal(SNES snes,Vec X,Mat *A,Mat *B,MatStructure *mstr,void *ctx) 97*ff35dfedSBarry Smith { 98*ff35dfedSBarry Smith PetscErrorCode ierr; 99*ff35dfedSBarry Smith DM dm; 100*ff35dfedSBarry Smith DMLocal_SNES *dmlocalsnes = (DMLocal_SNES*)ctx; 101*ff35dfedSBarry Smith Vec Xloc; 102*ff35dfedSBarry Smith 103*ff35dfedSBarry Smith PetscFunctionBegin; 104*ff35dfedSBarry Smith ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 105*ff35dfedSBarry Smith if (dmlocalsnes->jacobianlocal) { 106*ff35dfedSBarry Smith ierr = DMGetLocalVector(dm,&Xloc);CHKERRQ(ierr); 107*ff35dfedSBarry Smith ierr = VecZeroEntries(Xloc);CHKERRQ(ierr); 108*ff35dfedSBarry Smith ierr = DMGlobalToLocalBegin(dm,X,INSERT_VALUES,Xloc);CHKERRQ(ierr); 109*ff35dfedSBarry Smith ierr = DMGlobalToLocalEnd(dm,X,INSERT_VALUES,Xloc);CHKERRQ(ierr); 110*ff35dfedSBarry Smith CHKMEMQ; 111*ff35dfedSBarry Smith ierr = (*dmlocalsnes->jacobianlocal)(dm,Xloc,*A,*B,mstr,dmlocalsnes->jacobianlocalctx);CHKERRQ(ierr); 112*ff35dfedSBarry Smith CHKMEMQ; 113*ff35dfedSBarry Smith ierr = DMRestoreLocalVector(dm,&Xloc);CHKERRQ(ierr); 114*ff35dfedSBarry Smith } else { 115*ff35dfedSBarry Smith MatFDColoring fdcoloring; 116*ff35dfedSBarry Smith ierr = PetscObjectQuery((PetscObject)dm,"DMDASNES_FDCOLORING",(PetscObject*)&fdcoloring);CHKERRQ(ierr); 117*ff35dfedSBarry Smith if (!fdcoloring) { 118*ff35dfedSBarry Smith ISColoring coloring; 119*ff35dfedSBarry Smith 120*ff35dfedSBarry Smith ierr = DMCreateColoring(dm,dm->coloringtype,dm->mattype,&coloring);CHKERRQ(ierr); 121*ff35dfedSBarry Smith ierr = MatFDColoringCreate(*B,coloring,&fdcoloring);CHKERRQ(ierr); 122*ff35dfedSBarry Smith ierr = ISColoringDestroy(&coloring);CHKERRQ(ierr); 123*ff35dfedSBarry Smith switch (dm->coloringtype) { 124*ff35dfedSBarry Smith case IS_COLORING_GLOBAL: 125*ff35dfedSBarry Smith ierr = MatFDColoringSetFunction(fdcoloring,(PetscErrorCode(*)(void))SNESComputeFunction_DMLocal,dmlocalsnes);CHKERRQ(ierr); 126*ff35dfedSBarry Smith break; 127*ff35dfedSBarry Smith default: SETERRQ1(((PetscObject)snes)->comm,PETSC_ERR_SUP,"No support for coloring type '%s'",ISColoringTypes[dm->coloringtype]); 128*ff35dfedSBarry Smith } 129*ff35dfedSBarry Smith ierr = PetscObjectSetOptionsPrefix((PetscObject)fdcoloring,((PetscObject)dm)->prefix);CHKERRQ(ierr); 130*ff35dfedSBarry Smith ierr = MatFDColoringSetFromOptions(fdcoloring);CHKERRQ(ierr); 131*ff35dfedSBarry Smith ierr = PetscObjectCompose((PetscObject)dm,"DMDASNES_FDCOLORING",(PetscObject)fdcoloring);CHKERRQ(ierr); 132*ff35dfedSBarry Smith ierr = PetscObjectDereference((PetscObject)fdcoloring);CHKERRQ(ierr); 133*ff35dfedSBarry Smith 134*ff35dfedSBarry Smith /* The following breaks an ugly reference counting loop that deserves a paragraph. MatFDColoringApply() will call 135*ff35dfedSBarry Smith * VecDuplicate() with the state Vec and store inside the MatFDColoring. This Vec will duplicate the Vec, but the 136*ff35dfedSBarry Smith * MatFDColoring is composed with the DM. We dereference the DM here so that the reference count will eventually 137*ff35dfedSBarry Smith * drop to 0. Note the code in DMDestroy() that exits early for a negative reference count. That code path will be 138*ff35dfedSBarry Smith * taken when the PetscOList for the Vec inside MatFDColoring is destroyed. 139*ff35dfedSBarry Smith */ 140*ff35dfedSBarry Smith ierr = PetscObjectDereference((PetscObject)dm);CHKERRQ(ierr); 141*ff35dfedSBarry Smith } 142*ff35dfedSBarry Smith *mstr = SAME_NONZERO_PATTERN; 143*ff35dfedSBarry Smith ierr = MatFDColoringApply(*B,fdcoloring,X,mstr,snes);CHKERRQ(ierr); 144*ff35dfedSBarry Smith } 145*ff35dfedSBarry Smith /* This will be redundant if the user called both, but it's too common to forget. */ 146*ff35dfedSBarry Smith if (*A != *B) { 147*ff35dfedSBarry Smith ierr = MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 148*ff35dfedSBarry Smith ierr = MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 149*ff35dfedSBarry Smith } 150*ff35dfedSBarry Smith PetscFunctionReturn(0); 151*ff35dfedSBarry Smith } 152*ff35dfedSBarry Smith 153*ff35dfedSBarry Smith #undef __FUNCT__ 154*ff35dfedSBarry Smith #define __FUNCT__ "DMSNESSetFunctionLocal" 155*ff35dfedSBarry Smith /*@C 156*ff35dfedSBarry Smith DMSNESSetFunctionLocal - set a local residual evaluation function. This function is called with local vector 157*ff35dfedSBarry Smith containing the local vector information PLUS ghost point information. It should compute a result for all local 158*ff35dfedSBarry Smith elements and DMSNES will automatically accumulate the overlapping values. 159*ff35dfedSBarry Smith 160*ff35dfedSBarry Smith Logically Collective 161*ff35dfedSBarry Smith 162*ff35dfedSBarry Smith Input Arguments: 163*ff35dfedSBarry Smith + dm - DM to associate callback with 164*ff35dfedSBarry Smith . func - local residual evaluation 165*ff35dfedSBarry Smith - ctx - optional context for local residual evaluation 166*ff35dfedSBarry Smith 167*ff35dfedSBarry Smith Level: beginner 168*ff35dfedSBarry Smith 169*ff35dfedSBarry Smith .seealso: DMSNESSetFunction(), DMDASNESSetJacobianLocal(), DMDACreate1d(), DMDACreate2d(), DMDACreate3d() 170*ff35dfedSBarry Smith @*/ 171*ff35dfedSBarry Smith PetscErrorCode DMSNESSetFunctionLocal(DM dm,PetscErrorCode (*func)(DM,Vec,Vec,void*),void *ctx) 172*ff35dfedSBarry Smith { 173*ff35dfedSBarry Smith PetscErrorCode ierr; 174*ff35dfedSBarry Smith SNESDM sdm; 175*ff35dfedSBarry Smith DMLocal_SNES *dmlocalsnes; 176*ff35dfedSBarry Smith 177*ff35dfedSBarry Smith PetscFunctionBegin; 178*ff35dfedSBarry Smith PetscValidHeaderSpecific(dm,DM_CLASSID,1); 179*ff35dfedSBarry Smith ierr = DMSNESGetContextWrite(dm,&sdm);CHKERRQ(ierr); 180*ff35dfedSBarry Smith ierr = DMLocalSNESGetContext(dm,sdm,&dmlocalsnes);CHKERRQ(ierr); 181*ff35dfedSBarry Smith dmlocalsnes->residuallocal = func; 182*ff35dfedSBarry Smith dmlocalsnes->residuallocalctx = ctx; 183*ff35dfedSBarry Smith ierr = DMSNESSetFunction(dm,SNESComputeFunction_DMLocal,dmlocalsnes);CHKERRQ(ierr); 184*ff35dfedSBarry Smith if (!sdm->computejacobian) { /* Call us for the Jacobian too, can be overridden by the user. */ 185*ff35dfedSBarry Smith ierr = DMSNESSetJacobian(dm,SNESComputeJacobian_DMLocal,dmlocalsnes);CHKERRQ(ierr); 186*ff35dfedSBarry Smith } 187*ff35dfedSBarry Smith PetscFunctionReturn(0); 188*ff35dfedSBarry Smith } 189*ff35dfedSBarry Smith 190*ff35dfedSBarry Smith #undef __FUNCT__ 191*ff35dfedSBarry Smith #define __FUNCT__ "DMSNESSetJacobianLocal" 192*ff35dfedSBarry Smith /*@C 193*ff35dfedSBarry Smith DMSNESSetJacobianLocal - set a local Jacobian evaluation function 194*ff35dfedSBarry Smith 195*ff35dfedSBarry Smith Logically Collective 196*ff35dfedSBarry Smith 197*ff35dfedSBarry Smith Input Arguments: 198*ff35dfedSBarry Smith + dm - DM to associate callback with 199*ff35dfedSBarry Smith . func - local Jacobian evaluation 200*ff35dfedSBarry Smith - ctx - optional context for local Jacobian evaluation 201*ff35dfedSBarry Smith 202*ff35dfedSBarry Smith Level: beginner 203*ff35dfedSBarry Smith 204*ff35dfedSBarry Smith .seealso: DMSNESSetJacobian(), DMDASNESSetJacobian(), DMDACreate1d(), DMDACreate2d(), DMDACreate3d() 205*ff35dfedSBarry Smith @*/ 206*ff35dfedSBarry Smith PetscErrorCode DMSNESSetJacobianLocal(DM dm,PetscErrorCode (*func)(DM,Vec,Mat,Mat,MatStructure*,void*),void *ctx) 207*ff35dfedSBarry Smith { 208*ff35dfedSBarry Smith PetscErrorCode ierr; 209*ff35dfedSBarry Smith SNESDM sdm; 210*ff35dfedSBarry Smith DMLocal_SNES *dmlocalsnes; 211*ff35dfedSBarry Smith 212*ff35dfedSBarry Smith PetscFunctionBegin; 213*ff35dfedSBarry Smith PetscValidHeaderSpecific(dm,DM_CLASSID,1); 214*ff35dfedSBarry Smith ierr = DMSNESGetContextWrite(dm,&sdm);CHKERRQ(ierr); 215*ff35dfedSBarry Smith ierr = DMLocalSNESGetContext(dm,sdm,&dmlocalsnes);CHKERRQ(ierr); 216*ff35dfedSBarry Smith dmlocalsnes->jacobianlocal = func; 217*ff35dfedSBarry Smith dmlocalsnes->jacobianlocalctx = ctx; 218*ff35dfedSBarry Smith ierr = DMSNESSetJacobian(dm,SNESComputeJacobian_DMLocal,dmlocalsnes);CHKERRQ(ierr); 219*ff35dfedSBarry Smith PetscFunctionReturn(0); 220*ff35dfedSBarry Smith } 221*ff35dfedSBarry Smith 222