xref: /petsc/src/dm/impls/shell/dmshell.c (revision aab5dc5fcd781d74e200e1d7baeece1047a637d0)
1 #include <petscdmshell.h>       /*I    "petscdmshell.h"  I*/
2 #include <petscmat.h>
3 #include <petsc-private/dmimpl.h>
4 
5 typedef struct  {
6   Vec        Xglobal;
7   Vec        Xlocal;
8   Mat        A;
9   VecScatter *gtol;
10   VecScatter *ltog;
11 } DM_Shell;
12 
13 #undef __FUNCT__
14 #define __FUNCT__ "DMGlobalToLocalBegin_Shell_Default"
15 /*@C
16    DMGlobalToLocalBegin_Shell_Default - Uses the GlobalToLocal VecScatter context set by the user to begin a global to local scatter
17    Collective
18 
19    Input Arguments:
20 +  dm - shell DM
21 .  g - global vector
22 .  mode - InsertMode
23 -  l - local vector
24 
25    Level: developer
26 
27 .seealso: DMGlobalToLocalEnd_Shell_Default()
28 @*/
29 static PetscErrorCode DMGlobalToLocalBegin_Shell_Default(DM dm,Vec g,InsertMode mode,Vec l)
30 {
31   PetscErrorCode ierr;
32   DM_Shell       *shell = (DM_Shell*)dm->data;
33 
34   PetscFunctionBegin;
35   ierr = VecScatterBegin(*(shell->gtol),g,l,mode,SCATTER_FORWARD);CHKERRQ(ierr);
36   PetscFunctionReturn(0);
37 }
38 
39 #undef __FUNCT__
40 #define __FUNCT__ "DMGlobalToLocalEnd_Shell_Default"
41 /*@C
42    DMGlobalToLocalEnd_Shell_Default - Uses the GlobalToLocal VecScatter context set by the user to end a global to local scatter
43    Collective
44 
45    Input Arguments:
46 +  dm - shell DM
47 .  g - global vector
48 .  mode - InsertMode
49 -  l - local vector
50 
51    Level: developer
52 
53 .seealso: DMGlobalToLocalBegin_Shell_Default()
54 @*/
55 static PetscErrorCode DMGlobalToLocalEnd_Shell_Default(DM dm,Vec g,InsertMode mode,Vec l)
56 {
57   PetscErrorCode ierr;
58   DM_Shell       *shell = (DM_Shell*)dm->data;
59 
60   PetscFunctionBegin;
61   ierr = VecScatterEnd(*(shell->gtol),g,l,mode,SCATTER_FORWARD);CHKERRQ(ierr);
62   PetscFunctionReturn(0);
63 }
64 
65 #undef __FUNCT__
66 #define __FUNCT__ "DMCreateMatrix_Shell"
67 static PetscErrorCode DMCreateMatrix_Shell(DM dm,MatType mtype,Mat *J)
68 {
69   PetscErrorCode ierr;
70   DM_Shell       *shell = (DM_Shell*)dm->data;
71   Mat            A;
72 
73   PetscFunctionBegin;
74   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
75   PetscValidPointer(J,3);
76   if (!shell->A) {
77     if (shell->Xglobal) {
78       PetscInt m,M;
79       ierr = PetscInfo(dm,"Naively creating matrix using global vector distribution without preallocation");CHKERRQ(ierr);
80       ierr = VecGetSize(shell->Xglobal,&M);CHKERRQ(ierr);
81       ierr = VecGetLocalSize(shell->Xglobal,&m);CHKERRQ(ierr);
82       ierr = MatCreate(PetscObjectComm((PetscObject)dm),&shell->A);CHKERRQ(ierr);
83       ierr = MatSetSizes(shell->A,m,m,M,M);CHKERRQ(ierr);
84       if (mtype) {ierr = MatSetType(shell->A,mtype);CHKERRQ(ierr);}
85       ierr = MatSetUp(shell->A);CHKERRQ(ierr);
86     } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMShellSetMatrix(), DMShellSetCreateMatrix(), or provide a vector");
87   }
88   A = shell->A;
89   /* the check below is tacky and incomplete */
90   if (mtype) {
91     PetscBool flg,aij,seqaij,mpiaij;
92     ierr = PetscObjectTypeCompare((PetscObject)A,mtype,&flg);CHKERRQ(ierr);
93     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
94     ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&mpiaij);CHKERRQ(ierr);
95     ierr = PetscStrcmp(mtype,MATAIJ,&aij);CHKERRQ(ierr);
96     if (!flg) {
97       if (!(aij & (seqaij || mpiaij))) SETERRQ2(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_NOTSAMETYPE,"Requested matrix of type %s, but only %s available",mtype,((PetscObject)A)->type_name);
98     }
99   }
100   if (((PetscObject)A)->refct < 2) { /* We have an exclusive reference so we can give it out */
101     ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
102     ierr = MatZeroEntries(A);CHKERRQ(ierr);
103     *J   = A;
104   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
105     ierr = MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,J);CHKERRQ(ierr);
106     ierr = MatZeroEntries(*J);CHKERRQ(ierr);
107   }
108   PetscFunctionReturn(0);
109 }
110 
111 #undef __FUNCT__
112 #define __FUNCT__ "DMCreateGlobalVector_Shell"
113 PetscErrorCode DMCreateGlobalVector_Shell(DM dm,Vec *gvec)
114 {
115   PetscErrorCode ierr;
116   DM_Shell       *shell = (DM_Shell*)dm->data;
117   Vec            X;
118 
119   PetscFunctionBegin;
120   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
121   PetscValidPointer(gvec,2);
122   *gvec = 0;
123   X     = shell->Xglobal;
124   if (!X) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMShellSetGlobalVector() or DMShellSetCreateGlobalVector()");
125   if (((PetscObject)X)->refct < 2) { /* We have an exclusive reference so we can give it out */
126     ierr  = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
127     ierr  = VecZeroEntries(X);CHKERRQ(ierr);
128     *gvec = X;
129   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
130     ierr = VecDuplicate(X,gvec);CHKERRQ(ierr);
131     ierr = VecZeroEntries(*gvec);CHKERRQ(ierr);
132   }
133   ierr = VecSetDM(*gvec,dm);CHKERRQ(ierr);
134   PetscFunctionReturn(0);
135 }
136 
137 #undef __FUNCT__
138 #define __FUNCT__ "DMCreateLocalVector_Shell"
139 PetscErrorCode DMCreateLocalVector_Shell(DM dm,Vec *gvec)
140 {
141   PetscErrorCode ierr;
142   DM_Shell       *shell = (DM_Shell*)dm->data;
143   Vec            X;
144 
145   PetscFunctionBegin;
146   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
147   PetscValidPointer(gvec,2);
148   *gvec = 0;
149   X     = shell->Xlocal;
150   if (!X) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMShellSetLocalVector() or DMShellSetCreateLocalVector()");
151   if (((PetscObject)X)->refct < 2) { /* We have an exclusive reference so we can give it out */
152     ierr  = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
153     ierr  = VecZeroEntries(X);CHKERRQ(ierr);
154     *gvec = X;
155   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
156     ierr = VecDuplicate(X,gvec);CHKERRQ(ierr);
157     ierr = VecZeroEntries(*gvec);CHKERRQ(ierr);
158   }
159   ierr = VecSetDM(*gvec,dm);CHKERRQ(ierr);
160   PetscFunctionReturn(0);
161 }
162 
163 #undef __FUNCT__
164 #define __FUNCT__ "DMShellSetMatrix"
165 /*@
166    DMShellSetMatrix - sets a template matrix associated with the DMShell
167 
168    Collective
169 
170    Input Arguments:
171 +  dm - shell DM
172 -  J - template matrix
173 
174    Level: advanced
175 
176 .seealso: DMCreateMatrix(), DMShellSetCreateMatrix()
177 @*/
178 PetscErrorCode DMShellSetMatrix(DM dm,Mat J)
179 {
180   DM_Shell       *shell = (DM_Shell*)dm->data;
181   PetscErrorCode ierr;
182   PetscBool      isshell;
183 
184   PetscFunctionBegin;
185   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
186   PetscValidHeaderSpecific(J,MAT_CLASSID,2);
187   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
188   if (!isshell) PetscFunctionReturn(0);
189   ierr     = PetscObjectReference((PetscObject)J);CHKERRQ(ierr);
190   ierr     = MatDestroy(&shell->A);CHKERRQ(ierr);
191   shell->A = J;
192   PetscFunctionReturn(0);
193 }
194 
195 #undef __FUNCT__
196 #define __FUNCT__ "DMShellSetCreateMatrix"
197 /*@C
198    DMShellSetCreateMatrix - sets the routine to create a matrix associated with the shell DM
199 
200    Logically Collective on DM
201 
202    Input Arguments:
203 +  dm - the shell DM
204 -  func - the function to create a matrix
205 
206    Level: advanced
207 
208 .seealso: DMCreateMatrix(), DMShellSetMatrix()
209 @*/
210 PetscErrorCode DMShellSetCreateMatrix(DM dm,PetscErrorCode (*func)(DM,MatType,Mat*))
211 {
212 
213   PetscFunctionBegin;
214   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
215   dm->ops->creatematrix = func;
216   PetscFunctionReturn(0);
217 }
218 
219 #undef __FUNCT__
220 #define __FUNCT__ "DMShellSetGlobalVector"
221 /*@
222    DMShellSetGlobalVector - sets a template global vector associated with the DMShell
223 
224    Logically Collective on DM
225 
226    Input Arguments:
227 +  dm - shell DM
228 -  X - template vector
229 
230    Level: advanced
231 
232 .seealso: DMCreateGlobalVector(), DMShellSetMatrix(), DMShellSetCreateGlobalVector()
233 @*/
234 PetscErrorCode DMShellSetGlobalVector(DM dm,Vec X)
235 {
236   DM_Shell       *shell = (DM_Shell*)dm->data;
237   PetscErrorCode ierr;
238   PetscBool      isshell;
239 
240   PetscFunctionBegin;
241   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
242   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
243   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
244   if (!isshell) PetscFunctionReturn(0);
245   ierr           = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
246   ierr           = VecDestroy(&shell->Xglobal);CHKERRQ(ierr);
247   shell->Xglobal = X;
248   PetscFunctionReturn(0);
249 }
250 
251 #undef __FUNCT__
252 #define __FUNCT__ "DMShellSetCreateGlobalVector"
253 /*@C
254    DMShellSetCreateGlobalVector - sets the routine to create a global vector associated with the shell DM
255 
256    Logically Collective
257 
258    Input Arguments:
259 +  dm - the shell DM
260 -  func - the creation routine
261 
262    Level: advanced
263 
264 .seealso: DMShellSetGlobalVector(), DMShellSetCreateMatrix()
265 @*/
266 PetscErrorCode DMShellSetCreateGlobalVector(DM dm,PetscErrorCode (*func)(DM,Vec*))
267 {
268 
269   PetscFunctionBegin;
270   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
271   dm->ops->createglobalvector = func;
272   PetscFunctionReturn(0);
273 }
274 
275 #undef __FUNCT__
276 #define __FUNCT__ "DMShellSetLocalVector"
277 /*@
278    DMShellSetLocalVector - sets a template local vector associated with the DMShell
279 
280    Logically Collective on DM
281 
282    Input Arguments:
283 +  dm - shell DM
284 -  X - template vector
285 
286    Level: advanced
287 
288 .seealso: DMCreateLocalVector(), DMShellSetMatrix(), DMShellSetCreateLocalVector()
289 @*/
290 PetscErrorCode DMShellSetLocalVector(DM dm,Vec X)
291 {
292   DM_Shell       *shell = (DM_Shell*)dm->data;
293   PetscErrorCode ierr;
294   PetscBool      isshell;
295 
296   PetscFunctionBegin;
297   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
298   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
299   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
300   if (!isshell) PetscFunctionReturn(0);
301   ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
302   ierr = VecDestroy(&shell->Xlocal);CHKERRQ(ierr);
303   shell->Xlocal = X;
304   PetscFunctionReturn(0);
305 }
306 
307 #undef __FUNCT__
308 #define __FUNCT__ "DMShellSetCreateLocalVector"
309 /*@C
310    DMShellSetCreateLocalVector - sets the routine to create a local vector associated with the shell DM
311 
312    Logically Collective
313 
314    Input Arguments:
315 +  dm - the shell DM
316 -  func - the creation routine
317 
318    Level: advanced
319 
320 .seealso: DMShellSetLocalVector(), DMShellSetCreateMatrix()
321 @*/
322 PetscErrorCode DMShellSetCreateLocalVector(DM dm,PetscErrorCode (*func)(DM,Vec*))
323 {
324 
325   PetscFunctionBegin;
326   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
327   dm->ops->createlocalvector = func;
328   PetscFunctionReturn(0);
329 }
330 
331 #undef __FUNCT__
332 #define __FUNCT__ "DMShellSetGlobalToLocal"
333 /*@C
334    DMShellSetGlobalToLocal - Sets the routines used to perform a global to local scatter
335 
336    Logically Collective on DM
337 
338    Input Arguments
339 +  dm - the shell DM
340 .  begin - the routine that begins the global to local scatter
341 -  end - the routine that ends the global to local scatter
342 
343    Level: advanced
344 
345 .seealso: DMShellSetLocalToGlobal()
346 @*/
347 PetscErrorCode DMShellSetGlobalToLocal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) {
348   PetscFunctionBegin;
349   dm->ops->globaltolocalbegin = begin;
350   dm->ops->globaltolocalend = end;
351   PetscFunctionReturn(0);
352 }
353 
354 #undef __FUNCT__
355 #define __FUNCT__ "DMShellSetLocalToGlobal"
356 /*@C
357    DMShellSetLocalToGlobal - Sets the routines used to perform a local to global scatter
358 
359    Logically Collective on DM
360 
361    Input Arguments
362 +  dm - the shell DM
363 .  begin - the routine that begins the local to global scatter
364 -  end - the routine that ends the local to global scatter
365 
366    Level: advanced
367 
368 .seealso: DMShellSetGlobalToLocal()
369 @*/
370 PetscErrorCode DMShellSetLocalToGlobal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) {
371   PetscFunctionBegin;
372   dm->ops->localtoglobalbegin = begin;
373   dm->ops->localtoglobalend = end;
374   PetscFunctionReturn(0);
375 }
376 
377 #undef __FUNCT__
378 #define __FUNCT__ "DMShellSetGlobalToLocalVecScatter"
379 /*@
380    DMShellSetGlobalToLocalVecScatter - Sets a VecScatter context for global to local communication
381 
382    Logically Collective on DM
383 
384    Input Arguments
385 +  dm - the shell DM
386 -  gtol - the global to local VecScatter context
387 
388    Level: advanced
389 
390 .seealso: DMShellSetGlobalToLocal()
391 @*/
392 PetscErrorCode DMShellSetGlobalToLocalVecScatter(DM dm, VecScatter *gtol)
393 {
394   DM_Shell       *shell = (DM_Shell*)dm->data;
395 
396   PetscFunctionBegin;
397   shell->gtol = gtol;
398   PetscFunctionReturn(0);
399 }
400 
401 #undef __FUNCT__
402 #define __FUNCT__ "DMDestroy_Shell"
403 static PetscErrorCode DMDestroy_Shell(DM dm)
404 {
405   PetscErrorCode ierr;
406   DM_Shell       *shell = (DM_Shell*)dm->data;
407 
408   PetscFunctionBegin;
409   ierr = MatDestroy(&shell->A);CHKERRQ(ierr);
410   ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr);
411   ierr = VecDestroy(&shell->Xlocal);CHKERRQ(ierr);
412   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
413   ierr = PetscFree(shell);CHKERRQ(ierr);
414   PetscFunctionReturn(0);
415 }
416 
417 #undef __FUNCT__
418 #define __FUNCT__ "DMView_Shell"
419 static PetscErrorCode DMView_Shell(DM dm,PetscViewer v)
420 {
421   PetscErrorCode ierr;
422   DM_Shell       *shell = (DM_Shell*)dm->data;
423 
424   PetscFunctionBegin;
425   ierr = VecView(shell->Xglobal,v);CHKERRQ(ierr);
426   PetscFunctionReturn(0);
427 }
428 
429 #undef __FUNCT__
430 #define __FUNCT__ "DMLoad_Shell"
431 static PetscErrorCode DMLoad_Shell(DM dm,PetscViewer v)
432 {
433   PetscErrorCode ierr;
434   DM_Shell       *shell = (DM_Shell*)dm->data;
435 
436   PetscFunctionBegin;
437   ierr = VecCreate(PetscObjectComm((PetscObject)dm),&shell->Xglobal);CHKERRQ(ierr);
438   ierr = VecLoad(shell->Xglobal,v);CHKERRQ(ierr);
439   PetscFunctionReturn(0);
440 }
441 
442 #undef __FUNCT__
443 #define __FUNCT__ "DMCreate_Shell"
444 PETSC_EXTERN PetscErrorCode DMCreate_Shell(DM dm)
445 {
446   PetscErrorCode ierr;
447   DM_Shell       *shell;
448 
449   PetscFunctionBegin;
450   ierr     = PetscNewLog(dm,DM_Shell,&shell);CHKERRQ(ierr);
451   dm->data = shell;
452 
453   ierr = PetscObjectChangeTypeName((PetscObject)dm,DMSHELL);CHKERRQ(ierr);
454 
455   dm->ops->destroy            = DMDestroy_Shell;
456   dm->ops->createglobalvector = DMCreateGlobalVector_Shell;
457   dm->ops->createlocalvector  = DMCreateLocalVector_Shell;
458   dm->ops->creatematrix       = DMCreateMatrix_Shell;
459   dm->ops->view               = DMView_Shell;
460   dm->ops->load               = DMLoad_Shell;
461   dm->ops->globaltolocalbegin = DMShellDefaultGlobalToLocalBegin;
462   dm->ops->globaltolocalend   = DMShellDefaultGlobalToLocalEnd;
463   PetscFunctionReturn(0);
464 }
465 
466 #undef __FUNCT__
467 #define __FUNCT__ "DMShellCreate"
468 /*@
469     DMShellCreate - Creates a shell DM object, used to manage user-defined problem data
470 
471     Collective on MPI_Comm
472 
473     Input Parameter:
474 .   comm - the processors that will share the global vector
475 
476     Output Parameters:
477 .   shell - the shell DM
478 
479     Level: advanced
480 
481 .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateLocalVector()
482 @*/
483 PetscErrorCode  DMShellCreate(MPI_Comm comm,DM *dm)
484 {
485   PetscErrorCode ierr;
486 
487   PetscFunctionBegin;
488   PetscValidPointer(dm,2);
489   ierr = DMCreate(comm,dm);CHKERRQ(ierr);
490   ierr = DMSetType(*dm,DMSHELL);CHKERRQ(ierr);
491   PetscFunctionReturn(0);
492 }
493 
494