xref: /petsc/src/dm/impls/shell/dmshell.c (revision 55daaa54699ee49b06f05d8aec7fa1c97c98aca7)
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   shell->gtol = gtol;
462   PetscFunctionReturn(0);
463 }
464 
465 #undef __FUNCT__
466 #define __FUNCT__ "DMShellSetLocalToGlobalVecScatter"
467 /*@
468    DMShellSetLocalToGlobalVecScatter - Sets a VecScatter context for local to global communication
469 
470    Logically Collective on DM
471 
472    Input Arguments
473 +  dm - the shell DM
474 -  ltog - the local to global VecScatter context
475 
476    Level: advanced
477 
478 .seealso: DMShellSetLocalToGlobal()
479 @*/
480 PetscErrorCode DMShellSetLocalToGlobalVecScatter(DM dm, VecScatter *ltog)
481 {
482   DM_Shell       *shell = (DM_Shell*)dm->data;
483 
484   PetscFunctionBegin;
485   shell->ltog = ltog;
486   PetscFunctionReturn(0);
487 }
488 
489 #undef __FUNCT__
490 #define __FUNCT__ "DMDestroy_Shell"
491 static PetscErrorCode DMDestroy_Shell(DM dm)
492 {
493   PetscErrorCode ierr;
494   DM_Shell       *shell = (DM_Shell*)dm->data;
495 
496   PetscFunctionBegin;
497   ierr = MatDestroy(&shell->A);CHKERRQ(ierr);
498   ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr);
499   ierr = VecDestroy(&shell->Xlocal);CHKERRQ(ierr);
500   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
501   ierr = PetscFree(shell);CHKERRQ(ierr);
502   PetscFunctionReturn(0);
503 }
504 
505 #undef __FUNCT__
506 #define __FUNCT__ "DMView_Shell"
507 static PetscErrorCode DMView_Shell(DM dm,PetscViewer v)
508 {
509   PetscErrorCode ierr;
510   DM_Shell       *shell = (DM_Shell*)dm->data;
511 
512   PetscFunctionBegin;
513   ierr = VecView(shell->Xglobal,v);CHKERRQ(ierr);
514   PetscFunctionReturn(0);
515 }
516 
517 #undef __FUNCT__
518 #define __FUNCT__ "DMLoad_Shell"
519 static PetscErrorCode DMLoad_Shell(DM dm,PetscViewer v)
520 {
521   PetscErrorCode ierr;
522   DM_Shell       *shell = (DM_Shell*)dm->data;
523 
524   PetscFunctionBegin;
525   ierr = VecCreate(PetscObjectComm((PetscObject)dm),&shell->Xglobal);CHKERRQ(ierr);
526   ierr = VecLoad(shell->Xglobal,v);CHKERRQ(ierr);
527   PetscFunctionReturn(0);
528 }
529 
530 #undef __FUNCT__
531 #define __FUNCT__ "DMCreate_Shell"
532 PETSC_EXTERN PetscErrorCode DMCreate_Shell(DM dm)
533 {
534   PetscErrorCode ierr;
535   DM_Shell       *shell;
536 
537   PetscFunctionBegin;
538   ierr     = PetscNewLog(dm,DM_Shell,&shell);CHKERRQ(ierr);
539   dm->data = shell;
540 
541   ierr = PetscObjectChangeTypeName((PetscObject)dm,DMSHELL);CHKERRQ(ierr);
542 
543   dm->ops->destroy            = DMDestroy_Shell;
544   dm->ops->createglobalvector = DMCreateGlobalVector_Shell;
545   dm->ops->createlocalvector  = DMCreateLocalVector_Shell;
546   dm->ops->creatematrix       = DMCreateMatrix_Shell;
547   dm->ops->view               = DMView_Shell;
548   dm->ops->load               = DMLoad_Shell;
549   dm->ops->globaltolocalbegin = DMGlobalToLocalBeginDefaultShell;
550   dm->ops->globaltolocalend   = DMGlobalToLocalEndDefaultShell;
551   dm->ops->localtoglobalbegin = DMLocalToGlobalBeginDefaultShell;
552   dm->ops->localtoglobalend   = DMLocalToGlobalEndDefaultShell;
553   PetscFunctionReturn(0);
554 }
555 
556 #undef __FUNCT__
557 #define __FUNCT__ "DMShellCreate"
558 /*@
559     DMShellCreate - Creates a shell DM object, used to manage user-defined problem data
560 
561     Collective on MPI_Comm
562 
563     Input Parameter:
564 .   comm - the processors that will share the global vector
565 
566     Output Parameters:
567 .   shell - the shell DM
568 
569     Level: advanced
570 
571 .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateLocalVector()
572 @*/
573 PetscErrorCode  DMShellCreate(MPI_Comm comm,DM *dm)
574 {
575   PetscErrorCode ierr;
576 
577   PetscFunctionBegin;
578   PetscValidPointer(dm,2);
579   ierr = DMCreate(comm,dm);CHKERRQ(ierr);
580   ierr = DMSetType(*dm,DMSHELL);CHKERRQ(ierr);
581   PetscFunctionReturn(0);
582 }
583 
584