xref: /petsc/src/dm/impls/shell/dmshell.c (revision e6e75211d226c622f451867f53ce5d558649ff4f)
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\n");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__ "DMShellSetCoarsen"
616 /*@C
617    DMShellSetCoarsen - Set the routine used to coarsen the shell DM
618 
619    Logically Collective on DM
620 
621    Input Arguments
622 +  dm - the shell DM
623 -  coarsen - the routine that coarsens the DM
624 
625    Level: advanced
626 
627 .seealso: DMShellSetRefine(), DMCoarsen()
628 @*/
629 PetscErrorCode DMShellSetCoarsen(DM dm, PetscErrorCode (*coarsen)(DM,MPI_Comm,DM*))
630 {
631   PetscErrorCode ierr;
632   PetscBool      isshell;
633 
634   PetscFunctionBegin;
635   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
636   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
637   if (!isshell) PetscFunctionReturn(0);
638   dm->ops->coarsen = coarsen;
639   PetscFunctionReturn(0);
640 }
641 
642 #undef __FUNCT__
643 #define __FUNCT__ "DMShellSetRefine"
644 /*@C
645    DMShellSetRefine - Set the routine used to refine the shell DM
646 
647    Logically Collective on DM
648 
649    Input Arguments
650 +  dm - the shell DM
651 -  refine - the routine that refines the DM
652 
653    Level: advanced
654 
655 .seealso: DMShellSetCoarsen(), DMRefine()
656 @*/
657 PetscErrorCode DMShellSetRefine(DM dm, PetscErrorCode (*refine)(DM,MPI_Comm,DM*))
658 {
659   PetscErrorCode ierr;
660   PetscBool      isshell;
661 
662   PetscFunctionBegin;
663   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
664   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
665   if (!isshell) PetscFunctionReturn(0);
666   dm->ops->refine = refine;
667   PetscFunctionReturn(0);
668 }
669 
670 #undef __FUNCT__
671 #define __FUNCT__ "DMShellSetCreateInterpolation"
672 /*@C
673    DMShellSetCreateInterpolation - Set the routine used to create the interpolation operator
674 
675    Logically Collective on DM
676 
677    Input Arguments
678 +  dm - the shell DM
679 -  interp - the routine to create the interpolation
680 
681    Level: advanced
682 
683 .seealso: DMShellSetCreateInjection(), DMCreateInterpolation()
684 @*/
685 PetscErrorCode DMShellSetCreateInterpolation(DM dm, PetscErrorCode (*interp)(DM,DM,Mat*,Vec*))
686 {
687   PetscErrorCode ierr;
688   PetscBool      isshell;
689 
690   PetscFunctionBegin;
691   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
692   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
693   if (!isshell) PetscFunctionReturn(0);
694   dm->ops->createinterpolation = interp;
695   PetscFunctionReturn(0);
696 }
697 
698 #undef __FUNCT__
699 #define __FUNCT__ "DMShellSetCreateInjection"
700 /*@C
701    DMShellSetCreateInjection - Set the routine used to create the injection operator
702 
703    Logically Collective on DM
704 
705    Input Arguments
706 +  dm - the shell DM
707 -  inject - the routine to create the injection
708 
709    Level: advanced
710 
711 .seealso: DMShellSetCreateInterpolation(), DMCreateInjection()
712 @*/
713 PetscErrorCode DMShellSetCreateInjection(DM dm, PetscErrorCode (*inject)(DM,DM,Mat*))
714 {
715   PetscErrorCode ierr;
716   PetscBool      isshell;
717 
718   PetscFunctionBegin;
719   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
720   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
721   if (!isshell) PetscFunctionReturn(0);
722   dm->ops->getinjection = inject;
723   PetscFunctionReturn(0);
724 }
725 
726 #undef __FUNCT__
727 #define __FUNCT__ "DMShellSetCreateFieldDecomposition"
728 /*@C
729    DMShellSetCreateFieldDecomposition - Set the routine used to create a decomposition of fields for the shell DM
730 
731    Logically Collective on DM
732 
733    Input Arguments
734 +  dm - the shell DM
735 -  decomp - the routine to create the decomposition
736 
737    Level: advanced
738 
739 .seealso: DMCreateFieldDecomposition()
740 @*/
741 PetscErrorCode DMShellSetCreateFieldDecomposition(DM dm, PetscErrorCode (*decomp)(DM,PetscInt*,char***, IS**,DM**))
742 {
743   PetscErrorCode ierr;
744   PetscBool      isshell;
745 
746   PetscFunctionBegin;
747   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
748   ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr);
749   if (!isshell) PetscFunctionReturn(0);
750   dm->ops->createfielddecomposition = decomp;
751   PetscFunctionReturn(0);
752 }
753 
754 #undef __FUNCT__
755 #define __FUNCT__ "DMDestroy_Shell"
756 static PetscErrorCode DMDestroy_Shell(DM dm)
757 {
758   PetscErrorCode ierr;
759   DM_Shell       *shell = (DM_Shell*)dm->data;
760 
761   PetscFunctionBegin;
762   ierr = MatDestroy(&shell->A);CHKERRQ(ierr);
763   ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr);
764   ierr = VecDestroy(&shell->Xlocal);CHKERRQ(ierr);
765   ierr = VecScatterDestroy(&shell->gtol);CHKERRQ(ierr);
766   ierr = VecScatterDestroy(&shell->ltog);CHKERRQ(ierr);
767   ierr = VecScatterDestroy(&shell->ltol);CHKERRQ(ierr);
768   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
769   ierr = PetscFree(shell);CHKERRQ(ierr);
770   PetscFunctionReturn(0);
771 }
772 
773 #undef __FUNCT__
774 #define __FUNCT__ "DMView_Shell"
775 static PetscErrorCode DMView_Shell(DM dm,PetscViewer v)
776 {
777   PetscErrorCode ierr;
778   DM_Shell       *shell = (DM_Shell*)dm->data;
779 
780   PetscFunctionBegin;
781   ierr = VecView(shell->Xglobal,v);CHKERRQ(ierr);
782   PetscFunctionReturn(0);
783 }
784 
785 #undef __FUNCT__
786 #define __FUNCT__ "DMLoad_Shell"
787 static PetscErrorCode DMLoad_Shell(DM dm,PetscViewer v)
788 {
789   PetscErrorCode ierr;
790   DM_Shell       *shell = (DM_Shell*)dm->data;
791 
792   PetscFunctionBegin;
793   ierr = VecCreate(PetscObjectComm((PetscObject)dm),&shell->Xglobal);CHKERRQ(ierr);
794   ierr = VecLoad(shell->Xglobal,v);CHKERRQ(ierr);
795   PetscFunctionReturn(0);
796 }
797 
798 #undef __FUNCT__
799 #define __FUNCT__ "DMCreateSubDM_Shell"
800 PetscErrorCode DMCreateSubDM_Shell(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm)
801 {
802   PetscErrorCode ierr;
803 
804   PetscFunctionBegin;
805   if (subdm) {ierr = DMShellCreate(PetscObjectComm((PetscObject) dm), subdm);CHKERRQ(ierr);}
806   ierr = DMCreateSubDM_Section_Private(dm, numFields, fields, is, subdm);CHKERRQ(ierr);
807   PetscFunctionReturn(0);
808 }
809 
810 #undef __FUNCT__
811 #define __FUNCT__ "DMCreate_Shell"
812 PETSC_EXTERN PetscErrorCode DMCreate_Shell(DM dm)
813 {
814   PetscErrorCode ierr;
815   DM_Shell       *shell;
816 
817   PetscFunctionBegin;
818   ierr     = PetscNewLog(dm,&shell);CHKERRQ(ierr);
819   dm->data = shell;
820 
821   ierr = PetscObjectChangeTypeName((PetscObject)dm,DMSHELL);CHKERRQ(ierr);
822 
823   dm->ops->destroy            = DMDestroy_Shell;
824   dm->ops->createglobalvector = DMCreateGlobalVector_Shell;
825   dm->ops->createlocalvector  = DMCreateLocalVector_Shell;
826   dm->ops->creatematrix       = DMCreateMatrix_Shell;
827   dm->ops->view               = DMView_Shell;
828   dm->ops->load               = DMLoad_Shell;
829   dm->ops->globaltolocalbegin = DMGlobalToLocalBeginDefaultShell;
830   dm->ops->globaltolocalend   = DMGlobalToLocalEndDefaultShell;
831   dm->ops->localtoglobalbegin = DMLocalToGlobalBeginDefaultShell;
832   dm->ops->localtoglobalend   = DMLocalToGlobalEndDefaultShell;
833   dm->ops->localtolocalbegin  = DMLocalToLocalBeginDefaultShell;
834   dm->ops->localtolocalend    = DMLocalToLocalEndDefaultShell;
835   dm->ops->createsubdm        = DMCreateSubDM_Shell;
836   PetscFunctionReturn(0);
837 }
838 
839 #undef __FUNCT__
840 #define __FUNCT__ "DMShellCreate"
841 /*@
842     DMShellCreate - Creates a shell DM object, used to manage user-defined problem data
843 
844     Collective on MPI_Comm
845 
846     Input Parameter:
847 .   comm - the processors that will share the global vector
848 
849     Output Parameters:
850 .   shell - the shell DM
851 
852     Level: advanced
853 
854 .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateLocalVector()
855 @*/
856 PetscErrorCode  DMShellCreate(MPI_Comm comm,DM *dm)
857 {
858   PetscErrorCode ierr;
859 
860   PetscFunctionBegin;
861   PetscValidPointer(dm,2);
862   ierr = DMCreate(comm,dm);CHKERRQ(ierr);
863   ierr = DMSetType(*dm,DMSHELL);CHKERRQ(ierr);
864   ierr = DMSetUp(*dm);CHKERRQ(ierr);
865   PetscFunctionReturn(0);
866 }
867 
868