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