1 #include <petsc/private/dmimpl.h>
2 #include <petsc/private/kspimpl.h> /*I "petscksp.h" I*/
3 #include <petscdm.h>
4 
DMKSPDestroy(DMKSP * kdm)5 static PetscErrorCode DMKSPDestroy(DMKSP *kdm)
6 {
7   PetscErrorCode ierr;
8 
9   PetscFunctionBegin;
10   if (!*kdm) PetscFunctionReturn(0);
11   PetscValidHeaderSpecific((*kdm),DMKSP_CLASSID,1);
12   if (--((PetscObject)(*kdm))->refct > 0) {*kdm = NULL; PetscFunctionReturn(0);}
13   if ((*kdm)->ops->destroy) {ierr = ((*kdm)->ops->destroy)(kdm);CHKERRQ(ierr);}
14   ierr = PetscHeaderDestroy(kdm);CHKERRQ(ierr);
15   PetscFunctionReturn(0);
16 }
17 
DMKSPCreate(MPI_Comm comm,DMKSP * kdm)18 static PetscErrorCode DMKSPCreate(MPI_Comm comm,DMKSP *kdm)
19 {
20   PetscErrorCode ierr;
21 
22   PetscFunctionBegin;
23   ierr = KSPInitializePackage();CHKERRQ(ierr);
24   ierr = PetscHeaderCreate(*kdm, DMKSP_CLASSID, "DMKSP", "DMKSP", "DMKSP", comm, DMKSPDestroy, NULL);CHKERRQ(ierr);
25   PetscFunctionReturn(0);
26 }
27 
28 
29 /* Attaches the DMKSP to the coarse level.
30  * Under what conditions should we copy versus duplicate?
31  */
DMCoarsenHook_DMKSP(DM dm,DM dmc,void * ctx)32 static PetscErrorCode DMCoarsenHook_DMKSP(DM dm,DM dmc,void *ctx)
33 {
34   PetscErrorCode ierr;
35 
36   PetscFunctionBegin;
37   ierr = DMCopyDMKSP(dm,dmc);CHKERRQ(ierr);
38   PetscFunctionReturn(0);
39 }
40 
41 /* Attaches the DMKSP to the coarse level.
42  * Under what conditions should we copy versus duplicate?
43  */
DMRefineHook_DMKSP(DM dm,DM dmc,void * ctx)44 static PetscErrorCode DMRefineHook_DMKSP(DM dm,DM dmc,void *ctx)
45 {
46   PetscErrorCode ierr;
47 
48   PetscFunctionBegin;
49   ierr = DMCopyDMKSP(dm,dmc);CHKERRQ(ierr);
50   PetscFunctionReturn(0);
51 }
52 
53 /*@C
54    DMKSPCopy - copies the information in a DMKSP to another DMKSP
55 
56    Not Collective
57 
58    Input Argument:
59 +  kdm - Original DMKSP
60 -  nkdm - DMKSP to receive the data, should have been created with DMKSPCreate()
61 
62    Level: developer
63 
64 .seealso: DMKSPCreate(), DMKSPDestroy()
65 @*/
DMKSPCopy(DMKSP kdm,DMKSP nkdm)66 PetscErrorCode DMKSPCopy(DMKSP kdm,DMKSP nkdm)
67 {
68   PetscErrorCode ierr;
69 
70   PetscFunctionBegin;
71   PetscValidHeaderSpecific(kdm,DMKSP_CLASSID,1);
72   PetscValidHeaderSpecific(nkdm,DMKSP_CLASSID,2);
73   nkdm->ops->computeoperators    = kdm->ops->computeoperators;
74   nkdm->ops->computerhs          = kdm->ops->computerhs;
75   nkdm->ops->computeinitialguess = kdm->ops->computeinitialguess;
76   nkdm->ops->destroy             = kdm->ops->destroy;
77   nkdm->ops->duplicate           = kdm->ops->duplicate;
78 
79   nkdm->operatorsctx    = kdm->operatorsctx;
80   nkdm->rhsctx          = kdm->rhsctx;
81   nkdm->initialguessctx = kdm->initialguessctx;
82   nkdm->data            = kdm->data;
83   /* nkdm->originaldm   = kdm->originaldm; */ /* No need since nkdm->originaldm will be immediately updated in caller DMGetDMKSPWrite */
84 
85   nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
86   nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
87   nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];
88 
89   /* implementation specific copy hooks */
90   if (kdm->ops->duplicate) {ierr = (*kdm->ops->duplicate)(kdm,nkdm);CHKERRQ(ierr);}
91   PetscFunctionReturn(0);
92 }
93 
94 /*@C
95    DMGetDMKSP - get read-only private DMKSP context from a DM
96 
97    Logically Collective
98 
99    Input Argument:
100 .  dm - DM to be used with KSP
101 
102    Output Argument:
103 .  snesdm - private DMKSP context
104 
105    Level: developer
106 
107    Notes:
108    Use DMGetDMKSPWrite() if write access is needed. The DMKSPSetXXX API should be used wherever possible.
109 
110 .seealso: DMGetDMKSPWrite()
111 @*/
DMGetDMKSP(DM dm,DMKSP * kspdm)112 PetscErrorCode DMGetDMKSP(DM dm,DMKSP *kspdm)
113 {
114   PetscErrorCode ierr;
115 
116   PetscFunctionBegin;
117   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
118   *kspdm = (DMKSP) dm->dmksp;
119   if (!*kspdm) {
120     ierr                 = PetscInfo(dm,"Creating new DMKSP\n");CHKERRQ(ierr);
121     ierr                 = DMKSPCreate(PetscObjectComm((PetscObject)dm),kspdm);CHKERRQ(ierr);
122     dm->dmksp            = (PetscObject) *kspdm;
123     (*kspdm)->originaldm = dm;
124     ierr                 = DMCoarsenHookAdd(dm,DMCoarsenHook_DMKSP,NULL,NULL);CHKERRQ(ierr);
125     ierr                 = DMRefineHookAdd(dm,DMRefineHook_DMKSP,NULL,NULL);CHKERRQ(ierr);
126   }
127   PetscFunctionReturn(0);
128 }
129 
130 /*@C
131    DMGetDMKSPWrite - get write access to private DMKSP context from a DM
132 
133    Logically Collective
134 
135    Input Argument:
136 .  dm - DM to be used with KSP
137 
138    Output Argument:
139 .  kspdm - private DMKSP context
140 
141    Level: developer
142 
143 .seealso: DMGetDMKSP()
144 @*/
DMGetDMKSPWrite(DM dm,DMKSP * kspdm)145 PetscErrorCode DMGetDMKSPWrite(DM dm,DMKSP *kspdm)
146 {
147   PetscErrorCode ierr;
148   DMKSP          kdm;
149 
150   PetscFunctionBegin;
151   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
152   ierr = DMGetDMKSP(dm,&kdm);CHKERRQ(ierr);
153   if (!kdm->originaldm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DMKSP has a NULL originaldm");
154   if (kdm->originaldm != dm) {  /* Copy on write */
155     DMKSP oldkdm = kdm;
156     ierr      = PetscInfo(dm,"Copying DMKSP due to write\n");CHKERRQ(ierr);
157     ierr      = DMKSPCreate(PetscObjectComm((PetscObject)dm),&kdm);CHKERRQ(ierr);
158     ierr      = DMKSPCopy(oldkdm,kdm);CHKERRQ(ierr);
159     ierr      = DMKSPDestroy((DMKSP*)&dm->dmksp);CHKERRQ(ierr);
160     dm->dmksp = (PetscObject)kdm;
161     kdm->originaldm = dm;
162   }
163   *kspdm = kdm;
164   PetscFunctionReturn(0);
165 }
166 
167 /*@C
168    DMCopyDMKSP - copies a DM context to a new DM
169 
170    Logically Collective
171 
172    Input Arguments:
173 +  dmsrc - DM to obtain context from
174 -  dmdest - DM to add context to
175 
176    Level: developer
177 
178    Note:
179    The context is copied by reference. This function does not ensure that a context exists.
180 
181 .seealso: DMGetDMKSP(), KSPSetDM()
182 @*/
DMCopyDMKSP(DM dmsrc,DM dmdest)183 PetscErrorCode DMCopyDMKSP(DM dmsrc,DM dmdest)
184 {
185   PetscErrorCode ierr;
186 
187   PetscFunctionBegin;
188   PetscValidHeaderSpecific(dmsrc,DM_CLASSID,1);
189   PetscValidHeaderSpecific(dmdest,DM_CLASSID,2);
190   ierr          = DMKSPDestroy((DMKSP*)&dmdest->dmksp);CHKERRQ(ierr);
191   dmdest->dmksp = dmsrc->dmksp;
192   ierr          = PetscObjectReference(dmdest->dmksp);CHKERRQ(ierr);
193   ierr          = DMCoarsenHookAdd(dmdest,DMCoarsenHook_DMKSP,NULL,NULL);CHKERRQ(ierr);
194   ierr          = DMRefineHookAdd(dmdest,DMRefineHook_DMKSP,NULL,NULL);CHKERRQ(ierr);
195   PetscFunctionReturn(0);
196 }
197 
198 /*@C
199    DMKSPSetComputeOperators - set KSP matrix evaluation function
200 
201    Not Collective
202 
203    Input Argument:
204 +  dm - DM to be used with KSP
205 .  func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
206 -  ctx - context for matrix evaluation
207 
208    Level: advanced
209 
210    Note:
211    KSPSetComputeOperators() is normally used, but it calls this function internally because the user context is actually
212    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
213    not. If DM took a more central role at some later date, this could become the primary method of setting the matrix.
214 
215 .seealso: DMKSPSetContext(), DMKSPGetComputeOperators(), KSPSetOperators()
216 @*/
DMKSPSetComputeOperators(DM dm,PetscErrorCode (* func)(KSP,Mat,Mat,void *),void * ctx)217 PetscErrorCode DMKSPSetComputeOperators(DM dm,PetscErrorCode (*func)(KSP,Mat,Mat,void*),void *ctx)
218 {
219   PetscErrorCode ierr;
220   DMKSP          kdm;
221 
222   PetscFunctionBegin;
223   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
224   ierr = DMGetDMKSPWrite(dm,&kdm);CHKERRQ(ierr);
225   if (func) kdm->ops->computeoperators = func;
226   if (ctx) kdm->operatorsctx = ctx;
227   PetscFunctionReturn(0);
228 }
229 
230 /*@C
231    DMKSPGetComputeOperators - get KSP matrix evaluation function
232 
233    Not Collective
234 
235    Input Argument:
236 .  dm - DM to be used with KSP
237 
238    Output Arguments:
239 +  func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
240 -  ctx - context for matrix evaluation
241 
242    Level: advanced
243 
244 .seealso: DMKSPSetContext(), KSPSetComputeOperators(), DMKSPSetComputeOperators()
245 @*/
DMKSPGetComputeOperators(DM dm,PetscErrorCode (** func)(KSP,Mat,Mat,void *),void * ctx)246 PetscErrorCode DMKSPGetComputeOperators(DM dm,PetscErrorCode (**func)(KSP,Mat,Mat,void*),void *ctx)
247 {
248   PetscErrorCode ierr;
249   DMKSP          kdm;
250 
251   PetscFunctionBegin;
252   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
253   ierr = DMGetDMKSP(dm,&kdm);CHKERRQ(ierr);
254   if (func) *func = kdm->ops->computeoperators;
255   if (ctx) *(void**)ctx = kdm->operatorsctx;
256   PetscFunctionReturn(0);
257 }
258 
259 /*@C
260    DMKSPSetComputeRHS - set KSP right hand side evaluation function
261 
262    Not Collective
263 
264    Input Argument:
265 +  dm - DM to be used with KSP
266 .  func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
267 -  ctx - context for right hand side evaluation
268 
269    Level: advanced
270 
271    Note:
272    KSPSetComputeRHS() is normally used, but it calls this function internally because the user context is actually
273    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
274    not. If DM took a more central role at some later date, this could become the primary method of setting the matrix.
275 
276 .seealso: DMKSPSetContext(), DMKSPGetComputeRHS(), KSPSetRHS()
277 @*/
DMKSPSetComputeRHS(DM dm,PetscErrorCode (* func)(KSP,Vec,void *),void * ctx)278 PetscErrorCode DMKSPSetComputeRHS(DM dm,PetscErrorCode (*func)(KSP,Vec,void*),void *ctx)
279 {
280   PetscErrorCode ierr;
281   DMKSP          kdm;
282 
283   PetscFunctionBegin;
284   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
285   ierr = DMGetDMKSPWrite(dm,&kdm);CHKERRQ(ierr);
286   if (func) kdm->ops->computerhs = func;
287   if (ctx) kdm->rhsctx = ctx;
288   PetscFunctionReturn(0);
289 }
290 
291 /*@C
292    DMKSPSetComputeInitialGuess - set KSP initial guess evaluation function
293 
294    Not Collective
295 
296    Input Argument:
297 +  dm - DM to be used with KSP
298 .  func - initial guess evaluation function, see KSPSetComputeInitialGuess() for calling sequence
299 -  ctx - context for right hand side evaluation
300 
301    Level: advanced
302 
303    Note:
304    KSPSetComputeInitialGuess() is normally used, but it calls this function internally because the user context is actually
305    associated with the DM.
306 
307 .seealso: DMKSPSetContext(), DMKSPGetComputeRHS(), KSPSetRHS()
308 @*/
DMKSPSetComputeInitialGuess(DM dm,PetscErrorCode (* func)(KSP,Vec,void *),void * ctx)309 PetscErrorCode DMKSPSetComputeInitialGuess(DM dm,PetscErrorCode (*func)(KSP,Vec,void*),void *ctx)
310 {
311   PetscErrorCode ierr;
312   DMKSP          kdm;
313 
314   PetscFunctionBegin;
315   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
316   ierr = DMGetDMKSPWrite(dm,&kdm);CHKERRQ(ierr);
317   if (func) kdm->ops->computeinitialguess = func;
318   if (ctx) kdm->initialguessctx = ctx;
319   PetscFunctionReturn(0);
320 }
321 
322 /*@C
323    DMKSPGetComputeRHS - get KSP right hand side evaluation function
324 
325    Not Collective
326 
327    Input Argument:
328 .  dm - DM to be used with KSP
329 
330    Output Arguments:
331 +  func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
332 -  ctx - context for right hand side evaluation
333 
334    Level: advanced
335 
336 .seealso: DMKSPSetContext(), KSPSetComputeRHS(), DMKSPSetComputeRHS()
337 @*/
DMKSPGetComputeRHS(DM dm,PetscErrorCode (** func)(KSP,Vec,void *),void * ctx)338 PetscErrorCode DMKSPGetComputeRHS(DM dm,PetscErrorCode (**func)(KSP,Vec,void*),void *ctx)
339 {
340   PetscErrorCode ierr;
341   DMKSP          kdm;
342 
343   PetscFunctionBegin;
344   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
345   ierr = DMGetDMKSP(dm,&kdm);CHKERRQ(ierr);
346   if (func) *func = kdm->ops->computerhs;
347   if (ctx) *(void**)ctx = kdm->rhsctx;
348   PetscFunctionReturn(0);
349 }
350 
351 /*@C
352    DMKSPGetComputeInitialGuess - get KSP initial guess evaluation function
353 
354    Not Collective
355 
356    Input Argument:
357 .  dm - DM to be used with KSP
358 
359    Output Arguments:
360 +  func - initial guess evaluation function, see KSPSetComputeInitialGuess() for calling sequence
361 -  ctx - context for right hand side evaluation
362 
363    Level: advanced
364 
365 .seealso: DMKSPSetContext(), KSPSetComputeRHS(), DMKSPSetComputeRHS()
366 @*/
DMKSPGetComputeInitialGuess(DM dm,PetscErrorCode (** func)(KSP,Vec,void *),void * ctx)367 PetscErrorCode DMKSPGetComputeInitialGuess(DM dm,PetscErrorCode (**func)(KSP,Vec,void*),void *ctx)
368 {
369   PetscErrorCode ierr;
370   DMKSP          kdm;
371 
372   PetscFunctionBegin;
373   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
374   ierr = DMGetDMKSP(dm,&kdm);CHKERRQ(ierr);
375   if (func) *func = kdm->ops->computeinitialguess;
376   if (ctx) *(void**)ctx = kdm->initialguessctx;
377   PetscFunctionReturn(0);
378 }
379