xref: /petsc/src/snes/utils/dmlocalsnes.c (revision ff35dfed30cd54218cdaf8727a0fd806f9e95d05)
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