xref: /petsc/src/dm/impls/shell/dmshell.c (revision a94b16f642dd020e133550c2839d2109d4396927)
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__ "DMGlobalToLocalBeginDefaultShell"
15 /*@
16    DMGlobalToLocalBeginDefaultShell - 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: advanced
26 
27    Note:  This is not normally called directly by user code, generally user code calls DMGlobalToLocalBegin() and DMGlobalToLocalEnd(). If the user provides their own custom routines to DMShellSetLocalToGlobal() then those routines might have reason to call this function.
28 
29 .seealso: DMGlobalToLocalEndDefaultShell()
30 @*/
31 PetscErrorCode DMGlobalToLocalBeginDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
32 {
33   PetscErrorCode ierr;
34   DM_Shell       *shell = (DM_Shell*)dm->data;
35 
36   PetscFunctionBegin;
37   if (!shell->gtol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
38   ierr = VecScatterBegin(shell->gtol,g,l,mode,SCATTER_FORWARD);CHKERRQ(ierr);
39   PetscFunctionReturn(0);
40 }
41 
42 #undef __FUNCT__
43 #define __FUNCT__ "DMGlobalToLocalEndDefaultShell"
44 /*@
45    DMGlobalToLocalEndDefaultShell - Uses the GlobalToLocal VecScatter context set by the user to end a global to local scatter
46    Collective
47 
48    Input Arguments:
49 +  dm - shell DM
50 .  g - global vector
51 .  mode - InsertMode
52 -  l - local vector
53 
54    Level: advanced
55 
56 .seealso: DMGlobalToLocalBeginDefaultShell()
57 @*/
58 PetscErrorCode DMGlobalToLocalEndDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
59 {
60   PetscErrorCode ierr;
61   DM_Shell       *shell = (DM_Shell*)dm->data;
62 
63   PetscFunctionBegin;
64    if (!shell->gtol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
65   ierr = VecScatterEnd(shell->gtol,g,l,mode,SCATTER_FORWARD);CHKERRQ(ierr);
66   PetscFunctionReturn(0);
67 }
68 
69 #undef __FUNCT__
70 #define __FUNCT__ "DMLocalToGlobalBeginDefaultShell"
71 /*@
72    DMLocalToGlobalBeginDefaultShell - Uses the LocalToGlobal VecScatter context set by the user to begin a local to global scatter
73    Collective
74 
75    Input Arguments:
76 +  dm - shell DM
77 .  l - local vector
78 .  mode - InsertMode
79 -  g - global vector
80 
81    Level: advanced
82 
83    Note:  This is not normally called directly by user code, generally user code calls DMLocalToGlobalBegin() and DMLocalToGlobalEnd(). If the user provides their own custom routines to DMShellSetLocalToGlobal() then those routines might have reason to call this function.
84 
85 .seealso: DMLocalToGlobalEndDefaultShell()
86 @*/
87 PetscErrorCode DMLocalToGlobalBeginDefaultShell(DM dm,Vec l,InsertMode mode,Vec g)
88 {
89   PetscErrorCode ierr;
90   DM_Shell       *shell = (DM_Shell*)dm->data;
91 
92   PetscFunctionBegin;
93   if (!shell->ltog) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToGlobalVecScatter()");
94   ierr = VecScatterBegin(shell->ltog,l,g,mode,SCATTER_FORWARD);CHKERRQ(ierr);
95   PetscFunctionReturn(0);
96 }
97 
98 #undef __FUNCT__
99 #define __FUNCT__ "DMLocalToGlobalEndDefaultShell"
100 /*@
101    DMLocalToGlobalEndDefaultShell - Uses the LocalToGlobal VecScatter context set by the user to end a local to global scatter
102    Collective
103 
104    Input Arguments:
105 +  dm - shell DM
106 .  l - local vector
107 .  mode - InsertMode
108 -  g - global vector
109 
110    Level: advanced
111 
112 .seealso: DMLocalToGlobalBeginDefaultShell()
113 @*/
114 PetscErrorCode DMLocalToGlobalEndDefaultShell(DM dm,Vec l,InsertMode mode,Vec g)
115 {
116   PetscErrorCode ierr;
117   DM_Shell       *shell = (DM_Shell*)dm->data;
118 
119   PetscFunctionBegin;
120    if (!shell->ltog) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToGlobalVecScatter()");
121   ierr = VecScatterEnd(shell->ltog,l,g,mode,SCATTER_FORWARD);CHKERRQ(ierr);
122   PetscFunctionReturn(0);
123 }
124 
125 
126 #undef __FUNCT__
127 #define __FUNCT__ "DMCreateMatrix_Shell"
128 static PetscErrorCode DMCreateMatrix_Shell(DM dm,MatType mtype,Mat *J)
129 {
130   PetscErrorCode ierr;
131   DM_Shell       *shell = (DM_Shell*)dm->data;
132   Mat            A;
133 
134   PetscFunctionBegin;
135   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
136   PetscValidPointer(J,3);
137   if (!shell->A) {
138     if (shell->Xglobal) {
139       PetscInt m,M;
140       ierr = PetscInfo(dm,"Naively creating matrix using global vector distribution without preallocation");CHKERRQ(ierr);
141       ierr = VecGetSize(shell->Xglobal,&M);CHKERRQ(ierr);
142       ierr = VecGetLocalSize(shell->Xglobal,&m);CHKERRQ(ierr);
143       ierr = MatCreate(PetscObjectComm((PetscObject)dm),&shell->A);CHKERRQ(ierr);
144       ierr = MatSetSizes(shell->A,m,m,M,M);CHKERRQ(ierr);
145       if (mtype) {ierr = MatSetType(shell->A,mtype);CHKERRQ(ierr);}
146       ierr = MatSetUp(shell->A);CHKERRQ(ierr);
147     } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMShellSetMatrix(), DMShellSetCreateMatrix(), or provide a vector");
148   }
149   A = shell->A;
150   /* the check below is tacky and incomplete */
151   if (mtype) {
152     PetscBool flg,aij,seqaij,mpiaij;
153     ierr = PetscObjectTypeCompare((PetscObject)A,mtype,&flg);CHKERRQ(ierr);
154     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
155     ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&mpiaij);CHKERRQ(ierr);
156     ierr = PetscStrcmp(mtype,MATAIJ,&aij);CHKERRQ(ierr);
157     if (!flg) {
158       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);
159     }
160   }
161   if (((PetscObject)A)->refct < 2) { /* We have an exclusive reference so we can give it out */
162     ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
163     ierr = MatZeroEntries(A);CHKERRQ(ierr);
164     *J   = A;
165   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
166     ierr = MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,J);CHKERRQ(ierr);
167     ierr = MatZeroEntries(*J);CHKERRQ(ierr);
168   }
169   PetscFunctionReturn(0);
170 }
171 
172 #undef __FUNCT__
173 #define __FUNCT__ "DMCreateGlobalVector_Shell"
174 PetscErrorCode DMCreateGlobalVector_Shell(DM dm,Vec *gvec)
175 {
176   PetscErrorCode ierr;
177   DM_Shell       *shell = (DM_Shell*)dm->data;
178   Vec            X;
179 
180   PetscFunctionBegin;
181   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
182   PetscValidPointer(gvec,2);
183   *gvec = 0;
184   X     = shell->Xglobal;
185   if (!X) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMShellSetGlobalVector() or DMShellSetCreateGlobalVector()");
186   if (((PetscObject)X)->refct < 2) { /* We have an exclusive reference so we can give it out */
187     ierr  = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
188     ierr  = VecZeroEntries(X);CHKERRQ(ierr);
189     *gvec = X;
190   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
191     ierr = VecDuplicate(X,gvec);CHKERRQ(ierr);
192     ierr = VecZeroEntries(*gvec);CHKERRQ(ierr);
193   }
194   ierr = VecSetDM(*gvec,dm);CHKERRQ(ierr);
195   PetscFunctionReturn(0);
196 }
197 
198 #undef __FUNCT__
199 #define __FUNCT__ "DMCreateLocalVector_Shell"
200 PetscErrorCode DMCreateLocalVector_Shell(DM dm,Vec *gvec)
201 {
202   PetscErrorCode ierr;
203   DM_Shell       *shell = (DM_Shell*)dm->data;
204   Vec            X;
205 
206   PetscFunctionBegin;
207   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
208   PetscValidPointer(gvec,2);
209   *gvec = 0;
210   X     = shell->Xlocal;
211   if (!X) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMShellSetLocalVector() or DMShellSetCreateLocalVector()");
212   if (((PetscObject)X)->refct < 2) { /* We have an exclusive reference so we can give it out */
213     ierr  = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
214     ierr  = VecZeroEntries(X);CHKERRQ(ierr);
215     *gvec = X;
216   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
217     ierr = VecDuplicate(X,gvec);CHKERRQ(ierr);
218     ierr = VecZeroEntries(*gvec);CHKERRQ(ierr);
219   }
220   ierr = VecSetDM(*gvec,dm);CHKERRQ(ierr);
221   PetscFunctionReturn(0);
222 }
223 
224 #undef __FUNCT__
225 #define __FUNCT__ "DMShellSetMatrix"
226 /*@
227    DMShellSetMatrix - sets a template matrix associated with the DMShell
228 
229    Collective
230 
231    Input Arguments:
232 +  dm - shell DM
233 -  J - template matrix
234 
235    Level: advanced
236 
237 .seealso: DMCreateMatrix(), DMShellSetCreateMatrix()
238 @*/
239 PetscErrorCode DMShellSetMatrix(DM dm,Mat J)
240 {
241   DM_Shell       *shell = (DM_Shell*)dm->data;
242   PetscErrorCode ierr;
243   PetscBool      isshell;
244 
245   PetscFunctionBegin;
246   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
247   PetscValidHeaderSpecific(J,MAT_CLASSID,2);
248   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
249   if (!isshell) PetscFunctionReturn(0);
250   ierr     = PetscObjectReference((PetscObject)J);CHKERRQ(ierr);
251   ierr     = MatDestroy(&shell->A);CHKERRQ(ierr);
252   shell->A = J;
253   PetscFunctionReturn(0);
254 }
255 
256 #undef __FUNCT__
257 #define __FUNCT__ "DMShellSetCreateMatrix"
258 /*@C
259    DMShellSetCreateMatrix - sets the routine to create a matrix associated with the shell DM
260 
261    Logically Collective on DM
262 
263    Input Arguments:
264 +  dm - the shell DM
265 -  func - the function to create a matrix
266 
267    Level: advanced
268 
269 .seealso: DMCreateMatrix(), DMShellSetMatrix()
270 @*/
271 PetscErrorCode DMShellSetCreateMatrix(DM dm,PetscErrorCode (*func)(DM,MatType,Mat*))
272 {
273 
274   PetscFunctionBegin;
275   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
276   dm->ops->creatematrix = func;
277   PetscFunctionReturn(0);
278 }
279 
280 #undef __FUNCT__
281 #define __FUNCT__ "DMShellSetGlobalVector"
282 /*@
283    DMShellSetGlobalVector - sets a template global vector associated with the DMShell
284 
285    Logically Collective on DM
286 
287    Input Arguments:
288 +  dm - shell DM
289 -  X - template vector
290 
291    Level: advanced
292 
293 .seealso: DMCreateGlobalVector(), DMShellSetMatrix(), DMShellSetCreateGlobalVector()
294 @*/
295 PetscErrorCode DMShellSetGlobalVector(DM dm,Vec X)
296 {
297   DM_Shell       *shell = (DM_Shell*)dm->data;
298   PetscErrorCode ierr;
299   PetscBool      isshell;
300 
301   PetscFunctionBegin;
302   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
303   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
304   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
305   if (!isshell) PetscFunctionReturn(0);
306   ierr           = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
307   ierr           = VecDestroy(&shell->Xglobal);CHKERRQ(ierr);
308   shell->Xglobal = X;
309   PetscFunctionReturn(0);
310 }
311 
312 #undef __FUNCT__
313 #define __FUNCT__ "DMShellSetCreateGlobalVector"
314 /*@C
315    DMShellSetCreateGlobalVector - sets the routine to create a global vector associated with the shell DM
316 
317    Logically Collective
318 
319    Input Arguments:
320 +  dm - the shell DM
321 -  func - the creation routine
322 
323    Level: advanced
324 
325 .seealso: DMShellSetGlobalVector(), DMShellSetCreateMatrix()
326 @*/
327 PetscErrorCode DMShellSetCreateGlobalVector(DM dm,PetscErrorCode (*func)(DM,Vec*))
328 {
329 
330   PetscFunctionBegin;
331   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
332   dm->ops->createglobalvector = func;
333   PetscFunctionReturn(0);
334 }
335 
336 #undef __FUNCT__
337 #define __FUNCT__ "DMShellSetLocalVector"
338 /*@
339    DMShellSetLocalVector - sets a template local vector associated with the DMShell
340 
341    Logically Collective on DM
342 
343    Input Arguments:
344 +  dm - shell DM
345 -  X - template vector
346 
347    Level: advanced
348 
349 .seealso: DMCreateLocalVector(), DMShellSetMatrix(), DMShellSetCreateLocalVector()
350 @*/
351 PetscErrorCode DMShellSetLocalVector(DM dm,Vec X)
352 {
353   DM_Shell       *shell = (DM_Shell*)dm->data;
354   PetscErrorCode ierr;
355   PetscBool      isshell;
356 
357   PetscFunctionBegin;
358   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
359   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
360   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
361   if (!isshell) PetscFunctionReturn(0);
362   ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
363   ierr = VecDestroy(&shell->Xlocal);CHKERRQ(ierr);
364   shell->Xlocal = X;
365   PetscFunctionReturn(0);
366 }
367 
368 #undef __FUNCT__
369 #define __FUNCT__ "DMShellSetCreateLocalVector"
370 /*@C
371    DMShellSetCreateLocalVector - sets the routine to create a local vector associated with the shell DM
372 
373    Logically Collective
374 
375    Input Arguments:
376 +  dm - the shell DM
377 -  func - the creation routine
378 
379    Level: advanced
380 
381 .seealso: DMShellSetLocalVector(), DMShellSetCreateMatrix()
382 @*/
383 PetscErrorCode DMShellSetCreateLocalVector(DM dm,PetscErrorCode (*func)(DM,Vec*))
384 {
385 
386   PetscFunctionBegin;
387   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
388   dm->ops->createlocalvector = func;
389   PetscFunctionReturn(0);
390 }
391 
392 #undef __FUNCT__
393 #define __FUNCT__ "DMShellSetGlobalToLocal"
394 /*@C
395    DMShellSetGlobalToLocal - Sets the routines used to perform a global to local scatter
396 
397    Logically Collective on DM
398 
399    Input Arguments
400 +  dm - the shell DM
401 .  begin - the routine that begins the global to local scatter
402 -  end - the routine that ends the global to local scatter
403 
404    Notes: If these functions are not provided but DMShellSetGlobalToLocalVecScatter() is called then
405    DMGlobalToLocalBeginDefaultShell() are used to to perform the transfers DMGlobalToLocalEndDefaultShell()
406 
407    Level: advanced
408 
409 .seealso: DMShellSetLocalToGlobal(), DMGlobalToLocalBeginDefaultShell(), DMGlobalToLocalEndDefaultShell()
410 @*/
411 PetscErrorCode DMShellSetGlobalToLocal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) {
412   PetscFunctionBegin;
413   dm->ops->globaltolocalbegin = begin;
414   dm->ops->globaltolocalend = end;
415   PetscFunctionReturn(0);
416 }
417 
418 #undef __FUNCT__
419 #define __FUNCT__ "DMShellSetLocalToGlobal"
420 /*@C
421    DMShellSetLocalToGlobal - Sets the routines used to perform a local to global scatter
422 
423    Logically Collective on DM
424 
425    Input Arguments
426 +  dm - the shell DM
427 .  begin - the routine that begins the local to global scatter
428 -  end - the routine that ends the local to global scatter
429 
430    Level: advanced
431 
432 .seealso: DMShellSetGlobalToLocal()
433 @*/
434 PetscErrorCode DMShellSetLocalToGlobal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) {
435   PetscFunctionBegin;
436   dm->ops->localtoglobalbegin = begin;
437   dm->ops->localtoglobalend = end;
438   PetscFunctionReturn(0);
439 }
440 
441 #undef __FUNCT__
442 #define __FUNCT__ "DMShellSetGlobalToLocalVecScatter"
443 /*@
444    DMShellSetGlobalToLocalVecScatter - Sets a VecScatter context for global to local communication
445 
446    Logically Collective on DM
447 
448    Input Arguments
449 +  dm - the shell DM
450 -  gtol - the global to local VecScatter context
451 
452    Level: advanced
453 
454 .seealso: DMShellSetGlobalToLocal()
455 @*/
456 PetscErrorCode DMShellSetGlobalToLocalVecScatter(DM dm, VecScatter gtol)
457 {
458   DM_Shell       *shell = (DM_Shell*)dm->data;
459 
460   PetscFunctionBegin;
461   PetscObjectReference((PetscObject)gtol);
462   shell->gtol = gtol;
463   PetscFunctionReturn(0);
464 }
465 
466 #undef __FUNCT__
467 #define __FUNCT__ "DMShellSetLocalToGlobalVecScatter"
468 /*@
469    DMShellSetLocalToGlobalVecScatter - Sets a VecScatter context for local to global communication
470 
471    Logically Collective on DM
472 
473    Input Arguments
474 +  dm - the shell DM
475 -  ltog - the local to global VecScatter context
476 
477    Level: advanced
478 
479 .seealso: DMShellSetLocalToGlobal()
480 @*/
481 PetscErrorCode DMShellSetLocalToGlobalVecScatter(DM dm, VecScatter ltog)
482 {
483   DM_Shell       *shell = (DM_Shell*)dm->data;
484 
485   PetscFunctionBegin;
486   PetscObjectReference((PetscObject)ltog);
487   shell->ltog = ltog;
488   PetscFunctionReturn(0);
489 }
490 
491 #undef __FUNCT__
492 #define __FUNCT__ "DMDestroy_Shell"
493 static PetscErrorCode DMDestroy_Shell(DM dm)
494 {
495   PetscErrorCode ierr;
496   DM_Shell       *shell = (DM_Shell*)dm->data;
497 
498   PetscFunctionBegin;
499   ierr = MatDestroy(&shell->A);CHKERRQ(ierr);
500   ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr);
501   ierr = VecDestroy(&shell->Xlocal);CHKERRQ(ierr);
502   ierr = VecScatterDestroy(&shell->gtol);CHKERRQ(ierr);
503   ierr = VecScatterDestroy(&shell->ltog);CHKERRQ(ierr);
504   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
505   ierr = PetscFree(shell);CHKERRQ(ierr);
506   PetscFunctionReturn(0);
507 }
508 
509 #undef __FUNCT__
510 #define __FUNCT__ "DMView_Shell"
511 static PetscErrorCode DMView_Shell(DM dm,PetscViewer v)
512 {
513   PetscErrorCode ierr;
514   DM_Shell       *shell = (DM_Shell*)dm->data;
515 
516   PetscFunctionBegin;
517   ierr = VecView(shell->Xglobal,v);CHKERRQ(ierr);
518   PetscFunctionReturn(0);
519 }
520 
521 #undef __FUNCT__
522 #define __FUNCT__ "DMLoad_Shell"
523 static PetscErrorCode DMLoad_Shell(DM dm,PetscViewer v)
524 {
525   PetscErrorCode ierr;
526   DM_Shell       *shell = (DM_Shell*)dm->data;
527 
528   PetscFunctionBegin;
529   ierr = VecCreate(PetscObjectComm((PetscObject)dm),&shell->Xglobal);CHKERRQ(ierr);
530   ierr = VecLoad(shell->Xglobal,v);CHKERRQ(ierr);
531   PetscFunctionReturn(0);
532 }
533 
534 #undef __FUNCT__
535 #define __FUNCT__ "DMCreate_Shell"
536 PETSC_EXTERN PetscErrorCode DMCreate_Shell(DM dm)
537 {
538   PetscErrorCode ierr;
539   DM_Shell       *shell;
540 
541   PetscFunctionBegin;
542   ierr     = PetscNewLog(dm,DM_Shell,&shell);CHKERRQ(ierr);
543   dm->data = shell;
544 
545   ierr = PetscObjectChangeTypeName((PetscObject)dm,DMSHELL);CHKERRQ(ierr);
546 
547   dm->ops->destroy            = DMDestroy_Shell;
548   dm->ops->createglobalvector = DMCreateGlobalVector_Shell;
549   dm->ops->createlocalvector  = DMCreateLocalVector_Shell;
550   dm->ops->creatematrix       = DMCreateMatrix_Shell;
551   dm->ops->view               = DMView_Shell;
552   dm->ops->load               = DMLoad_Shell;
553   dm->ops->globaltolocalbegin = DMGlobalToLocalBeginDefaultShell;
554   dm->ops->globaltolocalend   = DMGlobalToLocalEndDefaultShell;
555   dm->ops->localtoglobalbegin = DMLocalToGlobalBeginDefaultShell;
556   dm->ops->localtoglobalend   = DMLocalToGlobalEndDefaultShell;
557   PetscFunctionReturn(0);
558 }
559 
560 #undef __FUNCT__
561 #define __FUNCT__ "DMShellCreate"
562 /*@
563     DMShellCreate - Creates a shell DM object, used to manage user-defined problem data
564 
565     Collective on MPI_Comm
566 
567     Input Parameter:
568 .   comm - the processors that will share the global vector
569 
570     Output Parameters:
571 .   shell - the shell DM
572 
573     Level: advanced
574 
575 .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateLocalVector()
576 @*/
577 PetscErrorCode  DMShellCreate(MPI_Comm comm,DM *dm)
578 {
579   PetscErrorCode ierr;
580 
581   PetscFunctionBegin;
582   PetscValidPointer(dm,2);
583   ierr = DMCreate(comm,dm);CHKERRQ(ierr);
584   ierr = DMSetType(*dm,DMSHELL);CHKERRQ(ierr);
585   PetscFunctionReturn(0);
586 }
587 
588