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