xref: /petsc/src/dm/impls/shell/dmshell.c (revision 8556b5eb6d24048282742bdd6ce397a5c8264fe5)
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   VecScatter ltol;
12   void       *ctx;
13 } DM_Shell;
14 
15 #undef __FUNCT__
16 #define __FUNCT__ "DMGlobalToLocalBeginDefaultShell"
17 /*@
18    DMGlobalToLocalBeginDefaultShell - Uses the GlobalToLocal VecScatter context set by the user to begin a global to local scatter
19    Collective
20 
21    Input Arguments:
22 +  dm - shell DM
23 .  g - global vector
24 .  mode - InsertMode
25 -  l - local vector
26 
27    Level: advanced
28 
29    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.
30 
31 .seealso: DMGlobalToLocalEndDefaultShell()
32 @*/
33 PetscErrorCode DMGlobalToLocalBeginDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
34 {
35   PetscErrorCode ierr;
36   DM_Shell       *shell = (DM_Shell*)dm->data;
37 
38   PetscFunctionBegin;
39   if (!shell->gtol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
40   ierr = VecScatterBegin(shell->gtol,g,l,mode,SCATTER_FORWARD);CHKERRQ(ierr);
41   PetscFunctionReturn(0);
42 }
43 
44 #undef __FUNCT__
45 #define __FUNCT__ "DMGlobalToLocalEndDefaultShell"
46 /*@
47    DMGlobalToLocalEndDefaultShell - Uses the GlobalToLocal VecScatter context set by the user to end a global to local scatter
48    Collective
49 
50    Input Arguments:
51 +  dm - shell DM
52 .  g - global vector
53 .  mode - InsertMode
54 -  l - local vector
55 
56    Level: advanced
57 
58 .seealso: DMGlobalToLocalBeginDefaultShell()
59 @*/
60 PetscErrorCode DMGlobalToLocalEndDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
61 {
62   PetscErrorCode ierr;
63   DM_Shell       *shell = (DM_Shell*)dm->data;
64 
65   PetscFunctionBegin;
66    if (!shell->gtol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
67   ierr = VecScatterEnd(shell->gtol,g,l,mode,SCATTER_FORWARD);CHKERRQ(ierr);
68   PetscFunctionReturn(0);
69 }
70 
71 #undef __FUNCT__
72 #define __FUNCT__ "DMLocalToGlobalBeginDefaultShell"
73 /*@
74    DMLocalToGlobalBeginDefaultShell - Uses the LocalToGlobal VecScatter context set by the user to begin a local to global scatter
75    Collective
76 
77    Input Arguments:
78 +  dm - shell DM
79 .  l - local vector
80 .  mode - InsertMode
81 -  g - global vector
82 
83    Level: advanced
84 
85    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.
86 
87 .seealso: DMLocalToGlobalEndDefaultShell()
88 @*/
89 PetscErrorCode DMLocalToGlobalBeginDefaultShell(DM dm,Vec l,InsertMode mode,Vec g)
90 {
91   PetscErrorCode ierr;
92   DM_Shell       *shell = (DM_Shell*)dm->data;
93 
94   PetscFunctionBegin;
95   if (!shell->ltog) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToGlobalVecScatter()");
96   ierr = VecScatterBegin(shell->ltog,l,g,mode,SCATTER_FORWARD);CHKERRQ(ierr);
97   PetscFunctionReturn(0);
98 }
99 
100 #undef __FUNCT__
101 #define __FUNCT__ "DMLocalToGlobalEndDefaultShell"
102 /*@
103    DMLocalToGlobalEndDefaultShell - Uses the LocalToGlobal VecScatter context set by the user to end a local to global scatter
104    Collective
105 
106    Input Arguments:
107 +  dm - shell DM
108 .  l - local vector
109 .  mode - InsertMode
110 -  g - global vector
111 
112    Level: advanced
113 
114 .seealso: DMLocalToGlobalBeginDefaultShell()
115 @*/
116 PetscErrorCode DMLocalToGlobalEndDefaultShell(DM dm,Vec l,InsertMode mode,Vec g)
117 {
118   PetscErrorCode ierr;
119   DM_Shell       *shell = (DM_Shell*)dm->data;
120 
121   PetscFunctionBegin;
122    if (!shell->ltog) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToGlobalVecScatter()");
123   ierr = VecScatterEnd(shell->ltog,l,g,mode,SCATTER_FORWARD);CHKERRQ(ierr);
124   PetscFunctionReturn(0);
125 }
126 
127 #undef __FUNCT__
128 #define __FUNCT__ "DMLocalToLocalBeginDefaultShell"
129 /*@
130    DMLocalToLocalBeginDefaultShell - Uses the LocalToLocal VecScatter context set by the user to begin a local to local scatter
131    Collective
132 
133    Input Arguments:
134 +  dm - shell DM
135 .  g - the original local vector
136 -  mode - InsertMode
137 
138    Output Parameter:
139 .  l  - the local vector with correct ghost values
140 
141    Level: advanced
142 
143    Note:  This is not normally called directly by user code, generally user code calls DMLocalToLocalBegin() and DMLocalToLocalEnd(). If the user provides their own custom routines to DMShellSetLocalToLocal() then those routines might have reason to call this function.
144 
145 .seealso: DMLocalToLocalEndDefaultShell()
146 @*/
147 PetscErrorCode DMLocalToLocalBeginDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
148 {
149   PetscErrorCode ierr;
150   DM_Shell       *shell = (DM_Shell*)dm->data;
151 
152   PetscFunctionBegin;
153   if (!shell->ltol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToLocalVecScatter()");
154   ierr = VecScatterBegin(shell->ltol,g,l,mode,SCATTER_FORWARD);CHKERRQ(ierr);
155   PetscFunctionReturn(0);
156 }
157 
158 #undef __FUNCT__
159 #define __FUNCT__ "DMLocalToLocalEndDefaultShell"
160 /*@
161    DMLocalToLocalEndDefaultShell - Uses the LocalToLocal VecScatter context set by the user to end a local to local scatter
162    Collective
163 
164    Input Arguments:
165 +  dm - shell DM
166 .  g - the original local vector
167 -  mode - InsertMode
168 
169    Output Parameter:
170 .  l  - the local vector with correct ghost values
171 
172    Level: advanced
173 
174 .seealso: DMLocalToLocalBeginDefaultShell()
175 @*/
176 PetscErrorCode DMLocalToLocalEndDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
177 {
178   PetscErrorCode ierr;
179   DM_Shell       *shell = (DM_Shell*)dm->data;
180 
181   PetscFunctionBegin;
182    if (!shell->ltol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
183   ierr = VecScatterEnd(shell->ltol,g,l,mode,SCATTER_FORWARD);CHKERRQ(ierr);
184   PetscFunctionReturn(0);
185 }
186 
187 #undef __FUNCT__
188 #define __FUNCT__ "DMCreateMatrix_Shell"
189 static PetscErrorCode DMCreateMatrix_Shell(DM dm,Mat *J)
190 {
191   PetscErrorCode ierr;
192   DM_Shell       *shell = (DM_Shell*)dm->data;
193   Mat            A;
194 
195   PetscFunctionBegin;
196   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
197   PetscValidPointer(J,3);
198   if (!shell->A) {
199     if (shell->Xglobal) {
200       PetscInt m,M;
201       ierr = PetscInfo(dm,"Naively creating matrix using global vector distribution without preallocation\n");CHKERRQ(ierr);
202       ierr = VecGetSize(shell->Xglobal,&M);CHKERRQ(ierr);
203       ierr = VecGetLocalSize(shell->Xglobal,&m);CHKERRQ(ierr);
204       ierr = MatCreate(PetscObjectComm((PetscObject)dm),&shell->A);CHKERRQ(ierr);
205       ierr = MatSetSizes(shell->A,m,m,M,M);CHKERRQ(ierr);
206       ierr = MatSetType(shell->A,dm->mattype);CHKERRQ(ierr);
207       ierr = MatSetUp(shell->A);CHKERRQ(ierr);
208     } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMShellSetMatrix(), DMShellSetCreateMatrix(), or provide a vector");
209   }
210   A = shell->A;
211   /* the check below is tacky and incomplete */
212   if (dm->mattype) {
213     PetscBool flg,aij,seqaij,mpiaij;
214     ierr = PetscObjectTypeCompare((PetscObject)A,dm->mattype,&flg);CHKERRQ(ierr);
215     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
216     ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&mpiaij);CHKERRQ(ierr);
217     ierr = PetscStrcmp(dm->mattype,MATAIJ,&aij);CHKERRQ(ierr);
218     if (!flg) {
219       if (!(aij && (seqaij || mpiaij))) SETERRQ2(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_NOTSAMETYPE,"Requested matrix of type %s, but only %s available",dm->mattype,((PetscObject)A)->type_name);
220     }
221   }
222   if (((PetscObject)A)->refct < 2) { /* We have an exclusive reference so we can give it out */
223     ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
224     ierr = MatZeroEntries(A);CHKERRQ(ierr);
225     *J   = A;
226   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
227     ierr = MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,J);CHKERRQ(ierr);
228     ierr = MatZeroEntries(*J);CHKERRQ(ierr);
229   }
230   PetscFunctionReturn(0);
231 }
232 
233 #undef __FUNCT__
234 #define __FUNCT__ "DMCreateGlobalVector_Shell"
235 PetscErrorCode DMCreateGlobalVector_Shell(DM dm,Vec *gvec)
236 {
237   PetscErrorCode ierr;
238   DM_Shell       *shell = (DM_Shell*)dm->data;
239   Vec            X;
240 
241   PetscFunctionBegin;
242   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
243   PetscValidPointer(gvec,2);
244   *gvec = 0;
245   X     = shell->Xglobal;
246   if (!X) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMShellSetGlobalVector() or DMShellSetCreateGlobalVector()");
247   if (((PetscObject)X)->refct < 2) { /* We have an exclusive reference so we can give it out */
248     ierr  = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
249     ierr  = VecZeroEntries(X);CHKERRQ(ierr);
250     *gvec = X;
251   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
252     ierr = VecDuplicate(X,gvec);CHKERRQ(ierr);
253     ierr = VecZeroEntries(*gvec);CHKERRQ(ierr);
254   }
255   ierr = VecSetDM(*gvec,dm);CHKERRQ(ierr);
256   PetscFunctionReturn(0);
257 }
258 
259 #undef __FUNCT__
260 #define __FUNCT__ "DMCreateLocalVector_Shell"
261 PetscErrorCode DMCreateLocalVector_Shell(DM dm,Vec *gvec)
262 {
263   PetscErrorCode ierr;
264   DM_Shell       *shell = (DM_Shell*)dm->data;
265   Vec            X;
266 
267   PetscFunctionBegin;
268   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
269   PetscValidPointer(gvec,2);
270   *gvec = 0;
271   X     = shell->Xlocal;
272   if (!X) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMShellSetLocalVector() or DMShellSetCreateLocalVector()");
273   if (((PetscObject)X)->refct < 2) { /* We have an exclusive reference so we can give it out */
274     ierr  = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
275     ierr  = VecZeroEntries(X);CHKERRQ(ierr);
276     *gvec = X;
277   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
278     ierr = VecDuplicate(X,gvec);CHKERRQ(ierr);
279     ierr = VecZeroEntries(*gvec);CHKERRQ(ierr);
280   }
281   ierr = VecSetDM(*gvec,dm);CHKERRQ(ierr);
282   PetscFunctionReturn(0);
283 }
284 
285 #undef __FUNCT__
286 #define __FUNCT__ "DMShellSetContext"
287 /*@
288    DMShellSetContext - set some data to be usable by this DM
289 
290    Collective
291 
292    Input Arguments:
293 +  dm - shell DM
294 -  ctx - the context
295 
296    Level: advanced
297 
298 .seealso: DMCreateMatrix(), DMShellGetContext()
299 @*/
300 PetscErrorCode DMShellSetContext(DM dm,void *ctx)
301 {
302   DM_Shell       *shell = (DM_Shell*)dm->data;
303   PetscErrorCode ierr;
304   PetscBool      isshell;
305 
306   PetscFunctionBegin;
307   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
308   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
309   if (!isshell) PetscFunctionReturn(0);
310   shell->ctx = ctx;
311   PetscFunctionReturn(0);
312 }
313 
314 #undef __FUNCT__
315 #define __FUNCT__ "DMShellGetContext"
316 /*@
317    DMShellGetContext - set some data to be usable by this DM
318 
319    Collective
320 
321    Input Argument:
322 .  dm - shell DM
323 
324    Output Argument:
325 .  ctx - the context
326 
327    Level: advanced
328 
329 .seealso: DMCreateMatrix(), DMShellSetContext()
330 @*/
331 PetscErrorCode DMShellGetContext(DM dm,void **ctx)
332 {
333   DM_Shell       *shell = (DM_Shell*)dm->data;
334   PetscErrorCode ierr;
335   PetscBool      isshell;
336 
337   PetscFunctionBegin;
338   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
339   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
340   if (!isshell) PetscFunctionReturn(0);
341   *ctx = shell->ctx;
342   PetscFunctionReturn(0);
343 }
344 
345 #undef __FUNCT__
346 #define __FUNCT__ "DMShellSetMatrix"
347 /*@
348    DMShellSetMatrix - sets a template matrix associated with the DMShell
349 
350    Collective
351 
352    Input Arguments:
353 +  dm - shell DM
354 -  J - template matrix
355 
356    Level: advanced
357 
358 .seealso: DMCreateMatrix(), DMShellSetCreateMatrix(), DMShellSetContext(), DMShellGetContext()
359 @*/
360 PetscErrorCode DMShellSetMatrix(DM dm,Mat J)
361 {
362   DM_Shell       *shell = (DM_Shell*)dm->data;
363   PetscErrorCode ierr;
364   PetscBool      isshell;
365 
366   PetscFunctionBegin;
367   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
368   PetscValidHeaderSpecific(J,MAT_CLASSID,2);
369   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
370   if (!isshell) PetscFunctionReturn(0);
371   ierr     = PetscObjectReference((PetscObject)J);CHKERRQ(ierr);
372   ierr     = MatDestroy(&shell->A);CHKERRQ(ierr);
373   shell->A = J;
374   PetscFunctionReturn(0);
375 }
376 
377 #undef __FUNCT__
378 #define __FUNCT__ "DMShellSetCreateMatrix"
379 /*@C
380    DMShellSetCreateMatrix - sets the routine to create a matrix associated with the shell DM
381 
382    Logically Collective on DM
383 
384    Input Arguments:
385 +  dm - the shell DM
386 -  func - the function to create a matrix
387 
388    Level: advanced
389 
390 .seealso: DMCreateMatrix(), DMShellSetMatrix(), DMShellSetContext(), DMShellGetContext()
391 @*/
392 PetscErrorCode DMShellSetCreateMatrix(DM dm,PetscErrorCode (*func)(DM,Mat*))
393 {
394 
395   PetscFunctionBegin;
396   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
397   dm->ops->creatematrix = func;
398   PetscFunctionReturn(0);
399 }
400 
401 #undef __FUNCT__
402 #define __FUNCT__ "DMShellSetGlobalVector"
403 /*@
404    DMShellSetGlobalVector - sets a template global vector associated with the DMShell
405 
406    Logically Collective on DM
407 
408    Input Arguments:
409 +  dm - shell DM
410 -  X - template vector
411 
412    Level: advanced
413 
414 .seealso: DMCreateGlobalVector(), DMShellSetMatrix(), DMShellSetCreateGlobalVector()
415 @*/
416 PetscErrorCode DMShellSetGlobalVector(DM dm,Vec X)
417 {
418   DM_Shell       *shell = (DM_Shell*)dm->data;
419   PetscErrorCode ierr;
420   PetscBool      isshell;
421 
422   PetscFunctionBegin;
423   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
424   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
425   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
426   if (!isshell) PetscFunctionReturn(0);
427   ierr           = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
428   ierr           = VecDestroy(&shell->Xglobal);CHKERRQ(ierr);
429   shell->Xglobal = X;
430   PetscFunctionReturn(0);
431 }
432 
433 #undef __FUNCT__
434 #define __FUNCT__ "DMShellSetCreateGlobalVector"
435 /*@C
436    DMShellSetCreateGlobalVector - sets the routine to create a global vector associated with the shell DM
437 
438    Logically Collective
439 
440    Input Arguments:
441 +  dm - the shell DM
442 -  func - the creation routine
443 
444    Level: advanced
445 
446 .seealso: DMShellSetGlobalVector(), DMShellSetCreateMatrix(), DMShellSetContext(), DMShellGetContext()
447 @*/
448 PetscErrorCode DMShellSetCreateGlobalVector(DM dm,PetscErrorCode (*func)(DM,Vec*))
449 {
450 
451   PetscFunctionBegin;
452   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
453   dm->ops->createglobalvector = func;
454   PetscFunctionReturn(0);
455 }
456 
457 #undef __FUNCT__
458 #define __FUNCT__ "DMShellSetLocalVector"
459 /*@
460    DMShellSetLocalVector - sets a template local vector associated with the DMShell
461 
462    Logically Collective on DM
463 
464    Input Arguments:
465 +  dm - shell DM
466 -  X - template vector
467 
468    Level: advanced
469 
470 .seealso: DMCreateLocalVector(), DMShellSetMatrix(), DMShellSetCreateLocalVector()
471 @*/
472 PetscErrorCode DMShellSetLocalVector(DM dm,Vec X)
473 {
474   DM_Shell       *shell = (DM_Shell*)dm->data;
475   PetscErrorCode ierr;
476   PetscBool      isshell;
477 
478   PetscFunctionBegin;
479   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
480   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
481   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
482   if (!isshell) PetscFunctionReturn(0);
483   ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
484   ierr = VecDestroy(&shell->Xlocal);CHKERRQ(ierr);
485   shell->Xlocal = X;
486   PetscFunctionReturn(0);
487 }
488 
489 #undef __FUNCT__
490 #define __FUNCT__ "DMShellSetCreateLocalVector"
491 /*@C
492    DMShellSetCreateLocalVector - sets the routine to create a local vector associated with the shell DM
493 
494    Logically Collective
495 
496    Input Arguments:
497 +  dm - the shell DM
498 -  func - the creation routine
499 
500    Level: advanced
501 
502 .seealso: DMShellSetLocalVector(), DMShellSetCreateMatrix(), DMShellSetContext(), DMShellGetContext()
503 @*/
504 PetscErrorCode DMShellSetCreateLocalVector(DM dm,PetscErrorCode (*func)(DM,Vec*))
505 {
506 
507   PetscFunctionBegin;
508   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
509   dm->ops->createlocalvector = func;
510   PetscFunctionReturn(0);
511 }
512 
513 #undef __FUNCT__
514 #define __FUNCT__ "DMShellSetGlobalToLocal"
515 /*@C
516    DMShellSetGlobalToLocal - Sets the routines used to perform a global to local scatter
517 
518    Logically Collective on DM
519 
520    Input Arguments
521 +  dm - the shell DM
522 .  begin - the routine that begins the global to local scatter
523 -  end - the routine that ends the global to local scatter
524 
525    Notes: If these functions are not provided but DMShellSetGlobalToLocalVecScatter() is called then
526    DMGlobalToLocalBeginDefaultShell()/DMGlobalToLocalEndDefaultShell() are used to to perform the transfers
527 
528    Level: advanced
529 
530 .seealso: DMShellSetLocalToGlobal(), DMGlobalToLocalBeginDefaultShell(), DMGlobalToLocalEndDefaultShell()
531 @*/
532 PetscErrorCode DMShellSetGlobalToLocal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) {
533   PetscFunctionBegin;
534   dm->ops->globaltolocalbegin = begin;
535   dm->ops->globaltolocalend = end;
536   PetscFunctionReturn(0);
537 }
538 
539 #undef __FUNCT__
540 #define __FUNCT__ "DMShellSetLocalToGlobal"
541 /*@C
542    DMShellSetLocalToGlobal - Sets the routines used to perform a local to global scatter
543 
544    Logically Collective on DM
545 
546    Input Arguments
547 +  dm - the shell DM
548 .  begin - the routine that begins the local to global scatter
549 -  end - the routine that ends the local to global scatter
550 
551    Notes: If these functions are not provided but DMShellSetLocalToGlobalVecScatter() is called then
552    DMLocalToGlobalBeginDefaultShell()/DMLocalToGlobalEndDefaultShell() are used to to perform the transfers
553 
554    Level: advanced
555 
556 .seealso: DMShellSetGlobalToLocal()
557 @*/
558 PetscErrorCode DMShellSetLocalToGlobal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) {
559   PetscFunctionBegin;
560   dm->ops->localtoglobalbegin = begin;
561   dm->ops->localtoglobalend = end;
562   PetscFunctionReturn(0);
563 }
564 
565 #undef __FUNCT__
566 #define __FUNCT__ "DMShellSetLocalToLocal"
567 /*@C
568    DMShellSetLocalToLocal - Sets the routines used to perform a local to local scatter
569 
570    Logically Collective on DM
571 
572    Input Arguments
573 +  dm - the shell DM
574 .  begin - the routine that begins the local to local scatter
575 -  end - the routine that ends the local to local scatter
576 
577    Notes: If these functions are not provided but DMShellSetLocalToLocalVecScatter() is called then
578    DMLocalToLocalBeginDefaultShell()/DMLocalToLocalEndDefaultShell() are used to to perform the transfers
579 
580    Level: advanced
581 
582 .seealso: DMShellSetGlobalToLocal(), DMLocalToLocalBeginDefaultShell(), DMLocalToLocalEndDefaultShell()
583 @*/
584 PetscErrorCode DMShellSetLocalToLocal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) {
585   PetscFunctionBegin;
586   dm->ops->localtolocalbegin = begin;
587   dm->ops->localtolocalend = end;
588   PetscFunctionReturn(0);
589 }
590 
591 #undef __FUNCT__
592 #define __FUNCT__ "DMShellSetGlobalToLocalVecScatter"
593 /*@
594    DMShellSetGlobalToLocalVecScatter - Sets a VecScatter context for global to local communication
595 
596    Logically Collective on DM
597 
598    Input Arguments
599 +  dm - the shell DM
600 -  gtol - the global to local VecScatter context
601 
602    Level: advanced
603 
604 .seealso: DMShellSetGlobalToLocal(), DMGlobalToLocalBeginDefaultShell(), DMGlobalToLocalEndDefaultShell()
605 @*/
606 PetscErrorCode DMShellSetGlobalToLocalVecScatter(DM dm, VecScatter gtol)
607 {
608   DM_Shell       *shell = (DM_Shell*)dm->data;
609   PetscErrorCode ierr;
610 
611   PetscFunctionBegin;
612   ierr = PetscObjectReference((PetscObject)gtol);CHKERRQ(ierr);
613   /* Call VecScatterDestroy() to avoid a memory leak in case of re-setting. */
614   ierr = VecScatterDestroy(&shell->gtol);CHKERRQ(ierr);
615   shell->gtol = gtol;
616   PetscFunctionReturn(0);
617 }
618 
619 #undef __FUNCT__
620 #define __FUNCT__ "DMShellSetLocalToGlobalVecScatter"
621 /*@
622    DMShellSetLocalToGlobalVecScatter - Sets a VecScatter context for local to global communication
623 
624    Logically Collective on DM
625 
626    Input Arguments
627 +  dm - the shell DM
628 -  ltog - the local to global VecScatter context
629 
630    Level: advanced
631 
632 .seealso: DMShellSetLocalToGlobal(), DMLocalToGlobalBeginDefaultShell(), DMLocalToGlobalEndDefaultShell()
633 @*/
634 PetscErrorCode DMShellSetLocalToGlobalVecScatter(DM dm, VecScatter ltog)
635 {
636   DM_Shell       *shell = (DM_Shell*)dm->data;
637   PetscErrorCode ierr;
638 
639   PetscFunctionBegin;
640   ierr = PetscObjectReference((PetscObject)ltog);CHKERRQ(ierr);
641   /* Call VecScatterDestroy() to avoid a memory leak in case of re-setting. */
642   ierr = VecScatterDestroy(&shell->ltog);CHKERRQ(ierr);
643   shell->ltog = ltog;
644   PetscFunctionReturn(0);
645 }
646 
647 #undef __FUNCT__
648 #define __FUNCT__ "DMShellSetLocalToLocalVecScatter"
649 /*@
650    DMShellSetLocalToLocalVecScatter - Sets a VecScatter context for local to local communication
651 
652    Logically Collective on DM
653 
654    Input Arguments
655 +  dm - the shell DM
656 -  ltol - the local to local VecScatter context
657 
658    Level: advanced
659 
660 .seealso: DMShellSetLocalToLocal(), DMLocalToLocalBeginDefaultShell(), DMLocalToLocalEndDefaultShell()
661 @*/
662 PetscErrorCode DMShellSetLocalToLocalVecScatter(DM dm, VecScatter ltol)
663 {
664   DM_Shell       *shell = (DM_Shell*)dm->data;
665   PetscErrorCode ierr;
666 
667   PetscFunctionBegin;
668   ierr = PetscObjectReference((PetscObject)ltol);CHKERRQ(ierr);
669   /* Call VecScatterDestroy() to avoid a memory leak in case of re-setting. */
670   ierr = VecScatterDestroy(&shell->ltol);CHKERRQ(ierr);
671   shell->ltol = ltol;
672   PetscFunctionReturn(0);
673 }
674 
675 #undef __FUNCT__
676 #define __FUNCT__ "DMShellSetCoarsen"
677 /*@C
678    DMShellSetCoarsen - Set the routine used to coarsen the shell DM
679 
680    Logically Collective on DM
681 
682    Input Arguments
683 +  dm - the shell DM
684 -  coarsen - the routine that coarsens the DM
685 
686    Level: advanced
687 
688 .seealso: DMShellSetRefine(), DMCoarsen(), DMShellSetContext(), DMShellGetContext()
689 @*/
690 PetscErrorCode DMShellSetCoarsen(DM dm, PetscErrorCode (*coarsen)(DM,MPI_Comm,DM*))
691 {
692   PetscErrorCode ierr;
693   PetscBool      isshell;
694 
695   PetscFunctionBegin;
696   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
697   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
698   if (!isshell) PetscFunctionReturn(0);
699   dm->ops->coarsen = coarsen;
700   PetscFunctionReturn(0);
701 }
702 
703 #undef __FUNCT__
704 #define __FUNCT__ "DMShellSetRefine"
705 /*@C
706    DMShellSetRefine - Set the routine used to refine the shell DM
707 
708    Logically Collective on DM
709 
710    Input Arguments
711 +  dm - the shell DM
712 -  refine - the routine that refines the DM
713 
714    Level: advanced
715 
716 .seealso: DMShellSetCoarsen(), DMRefine(), DMShellSetContext(), DMShellGetContext()
717 @*/
718 PetscErrorCode DMShellSetRefine(DM dm, PetscErrorCode (*refine)(DM,MPI_Comm,DM*))
719 {
720   PetscErrorCode ierr;
721   PetscBool      isshell;
722 
723   PetscFunctionBegin;
724   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
725   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
726   if (!isshell) PetscFunctionReturn(0);
727   dm->ops->refine = refine;
728   PetscFunctionReturn(0);
729 }
730 
731 #undef __FUNCT__
732 #define __FUNCT__ "DMShellSetCreateInterpolation"
733 /*@C
734    DMShellSetCreateInterpolation - Set the routine used to create the interpolation operator
735 
736    Logically Collective on DM
737 
738    Input Arguments
739 +  dm - the shell DM
740 -  interp - the routine to create the interpolation
741 
742    Level: advanced
743 
744 .seealso: DMShellSetCreateInjection(), DMCreateInterpolation(), DMShellSetCreateRestriction(), DMShellSetContext(), DMShellGetContext()
745 @*/
746 PetscErrorCode DMShellSetCreateInterpolation(DM dm, PetscErrorCode (*interp)(DM,DM,Mat*,Vec*))
747 {
748   PetscErrorCode ierr;
749   PetscBool      isshell;
750 
751   PetscFunctionBegin;
752   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
753   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
754   if (!isshell) PetscFunctionReturn(0);
755   dm->ops->createinterpolation = interp;
756   PetscFunctionReturn(0);
757 }
758 
759 #undef __FUNCT__
760 #define __FUNCT__ "DMShellSetCreateRestriction"
761 /*@C
762    DMShellSetCreateRestriction - Set the routine used to create the restriction operator
763 
764    Logically Collective on DM
765 
766    Input Arguments
767 +  dm - the shell DM
768 -  striction- the routine to create the restriction
769 
770    Level: advanced
771 
772 .seealso: DMShellSetCreateInjection(), DMCreateInterpolation(), DMShellSetContext(), DMShellGetContext()
773 @*/
774 PetscErrorCode DMShellSetCreateRestriction(DM dm, PetscErrorCode (*restriction)(DM,DM,Mat*))
775 {
776   PetscErrorCode ierr;
777   PetscBool      isshell;
778 
779   PetscFunctionBegin;
780   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
781   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
782   if (!isshell) PetscFunctionReturn(0);
783   dm->ops->createrestriction = restriction;
784   PetscFunctionReturn(0);
785 }
786 
787 #undef __FUNCT__
788 #define __FUNCT__ "DMShellSetCreateInjection"
789 /*@C
790    DMShellSetCreateInjection - Set the routine used to create the injection operator
791 
792    Logically Collective on DM
793 
794    Input Arguments
795 +  dm - the shell DM
796 -  inject - the routine to create the injection
797 
798    Level: advanced
799 
800 .seealso: DMShellSetCreateInterpolation(), DMCreateInjection(), DMShellSetContext(), DMShellGetContext()
801 @*/
802 PetscErrorCode DMShellSetCreateInjection(DM dm, PetscErrorCode (*inject)(DM,DM,Mat*))
803 {
804   PetscErrorCode ierr;
805   PetscBool      isshell;
806 
807   PetscFunctionBegin;
808   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
809   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
810   if (!isshell) PetscFunctionReturn(0);
811   dm->ops->getinjection = inject;
812   PetscFunctionReturn(0);
813 }
814 
815 #undef __FUNCT__
816 #define __FUNCT__ "DMShellSetCreateFieldDecomposition"
817 /*@C
818    DMShellSetCreateFieldDecomposition - Set the routine used to create a decomposition of fields for the shell DM
819 
820    Logically Collective on DM
821 
822    Input Arguments
823 +  dm - the shell DM
824 -  decomp - the routine to create the decomposition
825 
826    Level: advanced
827 
828 .seealso: DMCreateFieldDecomposition(), DMShellSetContext(), DMShellGetContext()
829 @*/
830 PetscErrorCode DMShellSetCreateFieldDecomposition(DM dm, PetscErrorCode (*decomp)(DM,PetscInt*,char***, IS**,DM**))
831 {
832   PetscErrorCode ierr;
833   PetscBool      isshell;
834 
835   PetscFunctionBegin;
836   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
837   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
838   if (!isshell) PetscFunctionReturn(0);
839   dm->ops->createfielddecomposition = decomp;
840   PetscFunctionReturn(0);
841 }
842 
843 /*@C
844    DMShellSetCreateSubDM - Set the routine used to create a sub DM from the shell DM
845 
846    Logically Collective on DM
847 
848    Input Arguments
849 +  dm - the shell DM
850 -  subdm - the routine to create the decomposition
851 
852    Level: advanced
853 
854 .seealso: DMCreateSubDM(), DMShellSetContext(), DMShellGetContext()
855 @*/
856 #undef __FUNCT__
857 #define __FUNCT__ "DMShellSetCreateSubDM"
858 PetscErrorCode DMShellSetCreateSubDM(DM dm, PetscErrorCode (*subdm)(DM,PetscInt,PetscInt[],IS*,DM*))
859 {
860   PetscErrorCode ierr;
861   PetscBool      isshell;
862 
863   PetscFunctionBegin;
864   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
865   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
866   if (!isshell) PetscFunctionReturn(0);
867   dm->ops->createsubdm = subdm;
868   PetscFunctionReturn(0);
869 }
870 
871 #undef __FUNCT__
872 #define __FUNCT__ "DMDestroy_Shell"
873 static PetscErrorCode DMDestroy_Shell(DM dm)
874 {
875   PetscErrorCode ierr;
876   DM_Shell       *shell = (DM_Shell*)dm->data;
877 
878   PetscFunctionBegin;
879   ierr = MatDestroy(&shell->A);CHKERRQ(ierr);
880   ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr);
881   ierr = VecDestroy(&shell->Xlocal);CHKERRQ(ierr);
882   ierr = VecScatterDestroy(&shell->gtol);CHKERRQ(ierr);
883   ierr = VecScatterDestroy(&shell->ltog);CHKERRQ(ierr);
884   ierr = VecScatterDestroy(&shell->ltol);CHKERRQ(ierr);
885   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
886   ierr = PetscFree(shell);CHKERRQ(ierr);
887   PetscFunctionReturn(0);
888 }
889 
890 #undef __FUNCT__
891 #define __FUNCT__ "DMView_Shell"
892 static PetscErrorCode DMView_Shell(DM dm,PetscViewer v)
893 {
894   PetscErrorCode ierr;
895   DM_Shell       *shell = (DM_Shell*)dm->data;
896 
897   PetscFunctionBegin;
898   ierr = VecView(shell->Xglobal,v);CHKERRQ(ierr);
899   PetscFunctionReturn(0);
900 }
901 
902 #undef __FUNCT__
903 #define __FUNCT__ "DMLoad_Shell"
904 static PetscErrorCode DMLoad_Shell(DM dm,PetscViewer v)
905 {
906   PetscErrorCode ierr;
907   DM_Shell       *shell = (DM_Shell*)dm->data;
908 
909   PetscFunctionBegin;
910   ierr = VecCreate(PetscObjectComm((PetscObject)dm),&shell->Xglobal);CHKERRQ(ierr);
911   ierr = VecLoad(shell->Xglobal,v);CHKERRQ(ierr);
912   PetscFunctionReturn(0);
913 }
914 
915 #undef __FUNCT__
916 #define __FUNCT__ "DMCreateSubDM_Shell"
917 PetscErrorCode DMCreateSubDM_Shell(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm)
918 {
919   PetscErrorCode ierr;
920 
921   PetscFunctionBegin;
922   if (subdm) {ierr = DMShellCreate(PetscObjectComm((PetscObject) dm), subdm);CHKERRQ(ierr);}
923   ierr = DMCreateSubDM_Section_Private(dm, numFields, fields, is, subdm);CHKERRQ(ierr);
924   PetscFunctionReturn(0);
925 }
926 
927 #undef __FUNCT__
928 #define __FUNCT__ "DMCreate_Shell"
929 PETSC_EXTERN PetscErrorCode DMCreate_Shell(DM dm)
930 {
931   PetscErrorCode ierr;
932   DM_Shell       *shell;
933 
934   PetscFunctionBegin;
935   ierr     = PetscNewLog(dm,&shell);CHKERRQ(ierr);
936   dm->data = shell;
937 
938   ierr = PetscObjectChangeTypeName((PetscObject)dm,DMSHELL);CHKERRQ(ierr);
939 
940   dm->ops->destroy            = DMDestroy_Shell;
941   dm->ops->createglobalvector = DMCreateGlobalVector_Shell;
942   dm->ops->createlocalvector  = DMCreateLocalVector_Shell;
943   dm->ops->creatematrix       = DMCreateMatrix_Shell;
944   dm->ops->view               = DMView_Shell;
945   dm->ops->load               = DMLoad_Shell;
946   dm->ops->globaltolocalbegin = DMGlobalToLocalBeginDefaultShell;
947   dm->ops->globaltolocalend   = DMGlobalToLocalEndDefaultShell;
948   dm->ops->localtoglobalbegin = DMLocalToGlobalBeginDefaultShell;
949   dm->ops->localtoglobalend   = DMLocalToGlobalEndDefaultShell;
950   dm->ops->localtolocalbegin  = DMLocalToLocalBeginDefaultShell;
951   dm->ops->localtolocalend    = DMLocalToLocalEndDefaultShell;
952   dm->ops->createsubdm        = DMCreateSubDM_Shell;
953   PetscFunctionReturn(0);
954 }
955 
956 #undef __FUNCT__
957 #define __FUNCT__ "DMShellCreate"
958 /*@
959     DMShellCreate - Creates a shell DM object, used to manage user-defined problem data
960 
961     Collective on MPI_Comm
962 
963     Input Parameter:
964 .   comm - the processors that will share the global vector
965 
966     Output Parameters:
967 .   shell - the shell DM
968 
969     Level: advanced
970 
971 .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateLocalVector(), DMShellSetContext(), DMShellGetContext()
972 @*/
973 PetscErrorCode  DMShellCreate(MPI_Comm comm,DM *dm)
974 {
975   PetscErrorCode ierr;
976 
977   PetscFunctionBegin;
978   PetscValidPointer(dm,2);
979   ierr = DMCreate(comm,dm);CHKERRQ(ierr);
980   ierr = DMSetType(*dm,DMSHELL);CHKERRQ(ierr);
981   ierr = DMSetUp(*dm);CHKERRQ(ierr);
982   PetscFunctionReturn(0);
983 }
984 
985