Actual source code: dmshell.c
petsc-3.7.7 2017-09-25
1: #include <petscdmshell.h> /*I "petscdmshell.h" I*/
2: #include <petscmat.h>
3: #include <petsc/private/dmimpl.h>
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;
17: /*@
18: DMGlobalToLocalBeginDefaultShell - Uses the GlobalToLocal VecScatter context set by the user to begin a global to local scatter
19: Collective
21: Input Arguments:
22: + dm - shell DM
23: . g - global vector
24: . mode - InsertMode
25: - l - local vector
27: Level: advanced
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.
31: .seealso: DMGlobalToLocalEndDefaultShell()
32: @*/
33: PetscErrorCode DMGlobalToLocalBeginDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
34: {
36: DM_Shell *shell = (DM_Shell*)dm->data;
39: if (!shell->gtol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
40: VecScatterBegin(shell->gtol,g,l,mode,SCATTER_FORWARD);
41: return(0);
42: }
46: /*@
47: DMGlobalToLocalEndDefaultShell - Uses the GlobalToLocal VecScatter context set by the user to end a global to local scatter
48: Collective
50: Input Arguments:
51: + dm - shell DM
52: . g - global vector
53: . mode - InsertMode
54: - l - local vector
56: Level: advanced
58: .seealso: DMGlobalToLocalBeginDefaultShell()
59: @*/
60: PetscErrorCode DMGlobalToLocalEndDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
61: {
63: DM_Shell *shell = (DM_Shell*)dm->data;
66: if (!shell->gtol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
67: VecScatterEnd(shell->gtol,g,l,mode,SCATTER_FORWARD);
68: return(0);
69: }
73: /*@
74: DMLocalToGlobalBeginDefaultShell - Uses the LocalToGlobal VecScatter context set by the user to begin a local to global scatter
75: Collective
77: Input Arguments:
78: + dm - shell DM
79: . l - local vector
80: . mode - InsertMode
81: - g - global vector
83: Level: advanced
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.
87: .seealso: DMLocalToGlobalEndDefaultShell()
88: @*/
89: PetscErrorCode DMLocalToGlobalBeginDefaultShell(DM dm,Vec l,InsertMode mode,Vec g)
90: {
92: DM_Shell *shell = (DM_Shell*)dm->data;
95: if (!shell->ltog) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToGlobalVecScatter()");
96: VecScatterBegin(shell->ltog,l,g,mode,SCATTER_FORWARD);
97: return(0);
98: }
102: /*@
103: DMLocalToGlobalEndDefaultShell - Uses the LocalToGlobal VecScatter context set by the user to end a local to global scatter
104: Collective
106: Input Arguments:
107: + dm - shell DM
108: . l - local vector
109: . mode - InsertMode
110: - g - global vector
112: Level: advanced
114: .seealso: DMLocalToGlobalBeginDefaultShell()
115: @*/
116: PetscErrorCode DMLocalToGlobalEndDefaultShell(DM dm,Vec l,InsertMode mode,Vec g)
117: {
119: DM_Shell *shell = (DM_Shell*)dm->data;
122: if (!shell->ltog) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToGlobalVecScatter()");
123: VecScatterEnd(shell->ltog,l,g,mode,SCATTER_FORWARD);
124: return(0);
125: }
129: /*@
130: DMLocalToLocalBeginDefaultShell - Uses the LocalToLocal VecScatter context set by the user to begin a local to local scatter
131: Collective
133: Input Arguments:
134: + dm - shell DM
135: . g - the original local vector
136: - mode - InsertMode
138: Output Parameter:
139: . l - the local vector with correct ghost values
141: Level: advanced
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.
145: .seealso: DMLocalToLocalEndDefaultShell()
146: @*/
147: PetscErrorCode DMLocalToLocalBeginDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
148: {
150: DM_Shell *shell = (DM_Shell*)dm->data;
153: if (!shell->ltol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToLocalVecScatter()");
154: VecScatterBegin(shell->ltol,g,l,mode,SCATTER_FORWARD);
155: return(0);
156: }
160: /*@
161: DMLocalToLocalEndDefaultShell - Uses the LocalToLocal VecScatter context set by the user to end a local to local scatter
162: Collective
164: Input Arguments:
165: + dm - shell DM
166: . g - the original local vector
167: - mode - InsertMode
169: Output Parameter:
170: . l - the local vector with correct ghost values
172: Level: advanced
174: .seealso: DMLocalToLocalBeginDefaultShell()
175: @*/
176: PetscErrorCode DMLocalToLocalEndDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
177: {
179: DM_Shell *shell = (DM_Shell*)dm->data;
182: if (!shell->ltol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
183: VecScatterEnd(shell->ltol,g,l,mode,SCATTER_FORWARD);
184: return(0);
185: }
189: static PetscErrorCode DMCreateMatrix_Shell(DM dm,Mat *J)
190: {
192: DM_Shell *shell = (DM_Shell*)dm->data;
193: Mat A;
198: if (!shell->A) {
199: if (shell->Xglobal) {
200: PetscInt m,M;
201: PetscInfo(dm,"Naively creating matrix using global vector distribution without preallocation\n");
202: VecGetSize(shell->Xglobal,&M);
203: VecGetLocalSize(shell->Xglobal,&m);
204: MatCreate(PetscObjectComm((PetscObject)dm),&shell->A);
205: MatSetSizes(shell->A,m,m,M,M);
206: MatSetType(shell->A,dm->mattype);
207: MatSetUp(shell->A);
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: PetscObjectTypeCompare((PetscObject)A,dm->mattype,&flg);
215: PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&seqaij);
216: PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&mpiaij);
217: PetscStrcmp(dm->mattype,MATAIJ,&aij);
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: PetscObjectReference((PetscObject)A);
224: MatZeroEntries(A);
225: *J = A;
226: } else { /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
227: MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,J);
228: MatZeroEntries(*J);
229: }
230: return(0);
231: }
235: PetscErrorCode DMCreateGlobalVector_Shell(DM dm,Vec *gvec)
236: {
238: DM_Shell *shell = (DM_Shell*)dm->data;
239: Vec X;
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: PetscObjectReference((PetscObject)X);
249: VecZeroEntries(X);
250: *gvec = X;
251: } else { /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
252: VecDuplicate(X,gvec);
253: VecZeroEntries(*gvec);
254: }
255: VecSetDM(*gvec,dm);
256: return(0);
257: }
261: PetscErrorCode DMCreateLocalVector_Shell(DM dm,Vec *gvec)
262: {
264: DM_Shell *shell = (DM_Shell*)dm->data;
265: Vec X;
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: PetscObjectReference((PetscObject)X);
275: VecZeroEntries(X);
276: *gvec = X;
277: } else { /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
278: VecDuplicate(X,gvec);
279: VecZeroEntries(*gvec);
280: }
281: VecSetDM(*gvec,dm);
282: return(0);
283: }
287: /*@
288: DMShellSetContext - set some data to be usable by this DM
290: Collective
292: Input Arguments:
293: + dm - shell DM
294: - ctx - the context
296: Level: advanced
298: .seealso: DMCreateMatrix(), DMShellGetContext()
299: @*/
300: PetscErrorCode DMShellSetContext(DM dm,void *ctx)
301: {
302: DM_Shell *shell = (DM_Shell*)dm->data;
304: PetscBool isshell;
308: PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
309: if (!isshell) return(0);
310: shell->ctx = ctx;
311: return(0);
312: }
316: /*@
317: DMShellGetContext - set some data to be usable by this DM
319: Collective
321: Input Argument:
322: . dm - shell DM
324: Output Argument:
325: . ctx - the context
327: Level: advanced
329: .seealso: DMCreateMatrix(), DMShellSetContext()
330: @*/
331: PetscErrorCode DMShellGetContext(DM dm,void **ctx)
332: {
333: DM_Shell *shell = (DM_Shell*)dm->data;
335: PetscBool isshell;
339: PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
340: if (!isshell) return(0);
341: *ctx = shell->ctx;
342: return(0);
343: }
347: /*@
348: DMShellSetMatrix - sets a template matrix associated with the DMShell
350: Collective
352: Input Arguments:
353: + dm - shell DM
354: - J - template matrix
356: Level: advanced
358: .seealso: DMCreateMatrix(), DMShellSetCreateMatrix(), DMShellSetContext(), DMShellGetContext()
359: @*/
360: PetscErrorCode DMShellSetMatrix(DM dm,Mat J)
361: {
362: DM_Shell *shell = (DM_Shell*)dm->data;
364: PetscBool isshell;
369: PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
370: if (!isshell) return(0);
371: PetscObjectReference((PetscObject)J);
372: MatDestroy(&shell->A);
373: shell->A = J;
374: return(0);
375: }
379: /*@C
380: DMShellSetCreateMatrix - sets the routine to create a matrix associated with the shell DM
382: Logically Collective on DM
384: Input Arguments:
385: + dm - the shell DM
386: - func - the function to create a matrix
388: Level: advanced
390: .seealso: DMCreateMatrix(), DMShellSetMatrix(), DMShellSetContext(), DMShellGetContext()
391: @*/
392: PetscErrorCode DMShellSetCreateMatrix(DM dm,PetscErrorCode (*func)(DM,Mat*))
393: {
397: dm->ops->creatematrix = func;
398: return(0);
399: }
403: /*@
404: DMShellSetGlobalVector - sets a template global vector associated with the DMShell
406: Logically Collective on DM
408: Input Arguments:
409: + dm - shell DM
410: - X - template vector
412: Level: advanced
414: .seealso: DMCreateGlobalVector(), DMShellSetMatrix(), DMShellSetCreateGlobalVector()
415: @*/
416: PetscErrorCode DMShellSetGlobalVector(DM dm,Vec X)
417: {
418: DM_Shell *shell = (DM_Shell*)dm->data;
420: PetscBool isshell;
425: PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
426: if (!isshell) return(0);
427: PetscObjectReference((PetscObject)X);
428: VecDestroy(&shell->Xglobal);
429: shell->Xglobal = X;
430: return(0);
431: }
435: /*@C
436: DMShellSetCreateGlobalVector - sets the routine to create a global vector associated with the shell DM
438: Logically Collective
440: Input Arguments:
441: + dm - the shell DM
442: - func - the creation routine
444: Level: advanced
446: .seealso: DMShellSetGlobalVector(), DMShellSetCreateMatrix(), DMShellSetContext(), DMShellGetContext()
447: @*/
448: PetscErrorCode DMShellSetCreateGlobalVector(DM dm,PetscErrorCode (*func)(DM,Vec*))
449: {
453: dm->ops->createglobalvector = func;
454: return(0);
455: }
459: /*@
460: DMShellSetLocalVector - sets a template local vector associated with the DMShell
462: Logically Collective on DM
464: Input Arguments:
465: + dm - shell DM
466: - X - template vector
468: Level: advanced
470: .seealso: DMCreateLocalVector(), DMShellSetMatrix(), DMShellSetCreateLocalVector()
471: @*/
472: PetscErrorCode DMShellSetLocalVector(DM dm,Vec X)
473: {
474: DM_Shell *shell = (DM_Shell*)dm->data;
476: PetscBool isshell;
481: PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
482: if (!isshell) return(0);
483: PetscObjectReference((PetscObject)X);
484: VecDestroy(&shell->Xlocal);
485: shell->Xlocal = X;
486: return(0);
487: }
491: /*@C
492: DMShellSetCreateLocalVector - sets the routine to create a local vector associated with the shell DM
494: Logically Collective
496: Input Arguments:
497: + dm - the shell DM
498: - func - the creation routine
500: Level: advanced
502: .seealso: DMShellSetLocalVector(), DMShellSetCreateMatrix(), DMShellSetContext(), DMShellGetContext()
503: @*/
504: PetscErrorCode DMShellSetCreateLocalVector(DM dm,PetscErrorCode (*func)(DM,Vec*))
505: {
509: dm->ops->createlocalvector = func;
510: return(0);
511: }
515: /*@C
516: DMShellSetGlobalToLocal - Sets the routines used to perform a global to local scatter
518: Logically Collective on DM
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
525: Notes: If these functions are not provided but DMShellSetGlobalToLocalVecScatter() is called then
526: DMGlobalToLocalBeginDefaultShell()/DMGlobalToLocalEndDefaultShell() are used to to perform the transfers
528: Level: advanced
530: .seealso: DMShellSetLocalToGlobal(), DMGlobalToLocalBeginDefaultShell(), DMGlobalToLocalEndDefaultShell()
531: @*/
532: PetscErrorCode DMShellSetGlobalToLocal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) {
534: dm->ops->globaltolocalbegin = begin;
535: dm->ops->globaltolocalend = end;
536: return(0);
537: }
541: /*@C
542: DMShellSetLocalToGlobal - Sets the routines used to perform a local to global scatter
544: Logically Collective on DM
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
551: Notes: If these functions are not provided but DMShellSetLocalToGlobalVecScatter() is called then
552: DMLocalToGlobalBeginDefaultShell()/DMLocalToGlobalEndDefaultShell() are used to to perform the transfers
554: Level: advanced
556: .seealso: DMShellSetGlobalToLocal()
557: @*/
558: PetscErrorCode DMShellSetLocalToGlobal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) {
560: dm->ops->localtoglobalbegin = begin;
561: dm->ops->localtoglobalend = end;
562: return(0);
563: }
567: /*@C
568: DMShellSetLocalToLocal - Sets the routines used to perform a local to local scatter
570: Logically Collective on DM
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
577: Notes: If these functions are not provided but DMShellSetLocalToLocalVecScatter() is called then
578: DMLocalToLocalBeginDefaultShell()/DMLocalToLocalEndDefaultShell() are used to to perform the transfers
580: Level: advanced
582: .seealso: DMShellSetGlobalToLocal(), DMLocalToLocalBeginDefaultShell(), DMLocalToLocalEndDefaultShell()
583: @*/
584: PetscErrorCode DMShellSetLocalToLocal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) {
586: dm->ops->localtolocalbegin = begin;
587: dm->ops->localtolocalend = end;
588: return(0);
589: }
593: /*@
594: DMShellSetGlobalToLocalVecScatter - Sets a VecScatter context for global to local communication
596: Logically Collective on DM
598: Input Arguments
599: + dm - the shell DM
600: - gtol - the global to local VecScatter context
602: Level: advanced
604: .seealso: DMShellSetGlobalToLocal(), DMGlobalToLocalBeginDefaultShell(), DMGlobalToLocalEndDefaultShell()
605: @*/
606: PetscErrorCode DMShellSetGlobalToLocalVecScatter(DM dm, VecScatter gtol)
607: {
608: DM_Shell *shell = (DM_Shell*)dm->data;
612: PetscObjectReference((PetscObject)gtol);
613: /* Call VecScatterDestroy() to avoid a memory leak in case of re-setting. */
614: VecScatterDestroy(&shell->gtol);
615: shell->gtol = gtol;
616: return(0);
617: }
621: /*@
622: DMShellSetLocalToGlobalVecScatter - Sets a VecScatter context for local to global communication
624: Logically Collective on DM
626: Input Arguments
627: + dm - the shell DM
628: - ltog - the local to global VecScatter context
630: Level: advanced
632: .seealso: DMShellSetLocalToGlobal(), DMLocalToGlobalBeginDefaultShell(), DMLocalToGlobalEndDefaultShell()
633: @*/
634: PetscErrorCode DMShellSetLocalToGlobalVecScatter(DM dm, VecScatter ltog)
635: {
636: DM_Shell *shell = (DM_Shell*)dm->data;
640: PetscObjectReference((PetscObject)ltog);
641: /* Call VecScatterDestroy() to avoid a memory leak in case of re-setting. */
642: VecScatterDestroy(&shell->ltog);
643: shell->ltog = ltog;
644: return(0);
645: }
649: /*@
650: DMShellSetLocalToLocalVecScatter - Sets a VecScatter context for local to local communication
652: Logically Collective on DM
654: Input Arguments
655: + dm - the shell DM
656: - ltol - the local to local VecScatter context
658: Level: advanced
660: .seealso: DMShellSetLocalToLocal(), DMLocalToLocalBeginDefaultShell(), DMLocalToLocalEndDefaultShell()
661: @*/
662: PetscErrorCode DMShellSetLocalToLocalVecScatter(DM dm, VecScatter ltol)
663: {
664: DM_Shell *shell = (DM_Shell*)dm->data;
668: PetscObjectReference((PetscObject)ltol);
669: /* Call VecScatterDestroy() to avoid a memory leak in case of re-setting. */
670: VecScatterDestroy(&shell->ltol);
671: shell->ltol = ltol;
672: return(0);
673: }
677: /*@C
678: DMShellSetCoarsen - Set the routine used to coarsen the shell DM
680: Logically Collective on DM
682: Input Arguments
683: + dm - the shell DM
684: - coarsen - the routine that coarsens the DM
686: Level: advanced
688: .seealso: DMShellSetRefine(), DMCoarsen(), DMShellSetContext(), DMShellGetContext()
689: @*/
690: PetscErrorCode DMShellSetCoarsen(DM dm, PetscErrorCode (*coarsen)(DM,MPI_Comm,DM*))
691: {
693: PetscBool isshell;
697: PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
698: if (!isshell) return(0);
699: dm->ops->coarsen = coarsen;
700: return(0);
701: }
705: /*@C
706: DMShellSetRefine - Set the routine used to refine the shell DM
708: Logically Collective on DM
710: Input Arguments
711: + dm - the shell DM
712: - refine - the routine that refines the DM
714: Level: advanced
716: .seealso: DMShellSetCoarsen(), DMRefine(), DMShellSetContext(), DMShellGetContext()
717: @*/
718: PetscErrorCode DMShellSetRefine(DM dm, PetscErrorCode (*refine)(DM,MPI_Comm,DM*))
719: {
721: PetscBool isshell;
725: PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
726: if (!isshell) return(0);
727: dm->ops->refine = refine;
728: return(0);
729: }
733: /*@C
734: DMShellSetCreateInterpolation - Set the routine used to create the interpolation operator
736: Logically Collective on DM
738: Input Arguments
739: + dm - the shell DM
740: - interp - the routine to create the interpolation
742: Level: advanced
744: .seealso: DMShellSetCreateInjection(), DMCreateInterpolation(), DMShellSetCreateRestriction(), DMShellSetContext(), DMShellGetContext()
745: @*/
746: PetscErrorCode DMShellSetCreateInterpolation(DM dm, PetscErrorCode (*interp)(DM,DM,Mat*,Vec*))
747: {
749: PetscBool isshell;
753: PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
754: if (!isshell) return(0);
755: dm->ops->createinterpolation = interp;
756: return(0);
757: }
761: /*@C
762: DMShellSetCreateRestriction - Set the routine used to create the restriction operator
764: Logically Collective on DM
766: Input Arguments
767: + dm - the shell DM
768: - striction- the routine to create the restriction
770: Level: advanced
772: .seealso: DMShellSetCreateInjection(), DMCreateInterpolation(), DMShellSetContext(), DMShellGetContext()
773: @*/
774: PetscErrorCode DMShellSetCreateRestriction(DM dm, PetscErrorCode (*restriction)(DM,DM,Mat*))
775: {
777: PetscBool isshell;
781: PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
782: if (!isshell) return(0);
783: dm->ops->createrestriction = restriction;
784: return(0);
785: }
789: /*@C
790: DMShellSetCreateInjection - Set the routine used to create the injection operator
792: Logically Collective on DM
794: Input Arguments
795: + dm - the shell DM
796: - inject - the routine to create the injection
798: Level: advanced
800: .seealso: DMShellSetCreateInterpolation(), DMCreateInjection(), DMShellSetContext(), DMShellGetContext()
801: @*/
802: PetscErrorCode DMShellSetCreateInjection(DM dm, PetscErrorCode (*inject)(DM,DM,Mat*))
803: {
805: PetscBool isshell;
809: PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
810: if (!isshell) return(0);
811: dm->ops->getinjection = inject;
812: return(0);
813: }
817: /*@C
818: DMShellSetCreateFieldDecomposition - Set the routine used to create a decomposition of fields for the shell DM
820: Logically Collective on DM
822: Input Arguments
823: + dm - the shell DM
824: - decomp - the routine to create the decomposition
826: Level: advanced
828: .seealso: DMCreateFieldDecomposition(), DMShellSetContext(), DMShellGetContext()
829: @*/
830: PetscErrorCode DMShellSetCreateFieldDecomposition(DM dm, PetscErrorCode (*decomp)(DM,PetscInt*,char***, IS**,DM**))
831: {
833: PetscBool isshell;
837: PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
838: if (!isshell) return(0);
839: dm->ops->createfielddecomposition = decomp;
840: return(0);
841: }
843: /*@C
844: DMShellSetCreateSubDM - Set the routine used to create a sub DM from the shell DM
846: Logically Collective on DM
848: Input Arguments
849: + dm - the shell DM
850: - subdm - the routine to create the decomposition
852: Level: advanced
854: .seealso: DMCreateSubDM(), DMShellSetContext(), DMShellGetContext()
855: @*/
858: PetscErrorCode DMShellSetCreateSubDM(DM dm, PetscErrorCode (*subdm)(DM,PetscInt,PetscInt[],IS*,DM*))
859: {
861: PetscBool isshell;
865: PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
866: if (!isshell) return(0);
867: dm->ops->createsubdm = subdm;
868: return(0);
869: }
873: static PetscErrorCode DMDestroy_Shell(DM dm)
874: {
876: DM_Shell *shell = (DM_Shell*)dm->data;
879: MatDestroy(&shell->A);
880: VecDestroy(&shell->Xglobal);
881: VecDestroy(&shell->Xlocal);
882: VecScatterDestroy(&shell->gtol);
883: VecScatterDestroy(&shell->ltog);
884: VecScatterDestroy(&shell->ltol);
885: /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
886: PetscFree(shell);
887: return(0);
888: }
892: static PetscErrorCode DMView_Shell(DM dm,PetscViewer v)
893: {
895: DM_Shell *shell = (DM_Shell*)dm->data;
898: VecView(shell->Xglobal,v);
899: return(0);
900: }
904: static PetscErrorCode DMLoad_Shell(DM dm,PetscViewer v)
905: {
907: DM_Shell *shell = (DM_Shell*)dm->data;
910: VecCreate(PetscObjectComm((PetscObject)dm),&shell->Xglobal);
911: VecLoad(shell->Xglobal,v);
912: return(0);
913: }
917: PetscErrorCode DMCreateSubDM_Shell(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm)
918: {
922: if (subdm) {DMShellCreate(PetscObjectComm((PetscObject) dm), subdm);}
923: DMCreateSubDM_Section_Private(dm, numFields, fields, is, subdm);
924: return(0);
925: }
929: PETSC_EXTERN PetscErrorCode DMCreate_Shell(DM dm)
930: {
932: DM_Shell *shell;
935: PetscNewLog(dm,&shell);
936: dm->data = shell;
938: PetscObjectChangeTypeName((PetscObject)dm,DMSHELL);
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: return(0);
954: }
958: /*@
959: DMShellCreate - Creates a shell DM object, used to manage user-defined problem data
961: Collective on MPI_Comm
963: Input Parameter:
964: . comm - the processors that will share the global vector
966: Output Parameters:
967: . shell - the shell DM
969: Level: advanced
971: .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateLocalVector(), DMShellSetContext(), DMShellGetContext()
972: @*/
973: PetscErrorCode DMShellCreate(MPI_Comm comm,DM *dm)
974: {
979: DMCreate(comm,dm);
980: DMSetType(*dm,DMSHELL);
981: DMSetUp(*dm);
982: return(0);
983: }