Actual source code: dmshell.c
petsc-3.5.4 2015-05-23
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: } DM_Shell;
16: /*@
17: DMGlobalToLocalBeginDefaultShell - Uses the GlobalToLocal VecScatter context set by the user to begin a global to local scatter
18: Collective
20: Input Arguments:
21: + dm - shell DM
22: . g - global vector
23: . mode - InsertMode
24: - l - local vector
26: Level: advanced
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.
30: .seealso: DMGlobalToLocalEndDefaultShell()
31: @*/
32: PetscErrorCode DMGlobalToLocalBeginDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
33: {
35: DM_Shell *shell = (DM_Shell*)dm->data;
38: if (!shell->gtol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
39: VecScatterBegin(shell->gtol,g,l,mode,SCATTER_FORWARD);
40: return(0);
41: }
45: /*@
46: DMGlobalToLocalEndDefaultShell - Uses the GlobalToLocal VecScatter context set by the user to end a global to local scatter
47: Collective
49: Input Arguments:
50: + dm - shell DM
51: . g - global vector
52: . mode - InsertMode
53: - l - local vector
55: Level: advanced
57: .seealso: DMGlobalToLocalBeginDefaultShell()
58: @*/
59: PetscErrorCode DMGlobalToLocalEndDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
60: {
62: DM_Shell *shell = (DM_Shell*)dm->data;
65: if (!shell->gtol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
66: VecScatterEnd(shell->gtol,g,l,mode,SCATTER_FORWARD);
67: return(0);
68: }
72: /*@
73: DMLocalToGlobalBeginDefaultShell - Uses the LocalToGlobal VecScatter context set by the user to begin a local to global scatter
74: Collective
76: Input Arguments:
77: + dm - shell DM
78: . l - local vector
79: . mode - InsertMode
80: - g - global vector
82: Level: advanced
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.
86: .seealso: DMLocalToGlobalEndDefaultShell()
87: @*/
88: PetscErrorCode DMLocalToGlobalBeginDefaultShell(DM dm,Vec l,InsertMode mode,Vec g)
89: {
91: DM_Shell *shell = (DM_Shell*)dm->data;
94: if (!shell->ltog) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToGlobalVecScatter()");
95: VecScatterBegin(shell->ltog,l,g,mode,SCATTER_FORWARD);
96: return(0);
97: }
101: /*@
102: DMLocalToGlobalEndDefaultShell - Uses the LocalToGlobal VecScatter context set by the user to end a local to global scatter
103: Collective
105: Input Arguments:
106: + dm - shell DM
107: . l - local vector
108: . mode - InsertMode
109: - g - global vector
111: Level: advanced
113: .seealso: DMLocalToGlobalBeginDefaultShell()
114: @*/
115: PetscErrorCode DMLocalToGlobalEndDefaultShell(DM dm,Vec l,InsertMode mode,Vec g)
116: {
118: DM_Shell *shell = (DM_Shell*)dm->data;
121: if (!shell->ltog) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToGlobalVecScatter()");
122: VecScatterEnd(shell->ltog,l,g,mode,SCATTER_FORWARD);
123: return(0);
124: }
128: /*@
129: DMLocalToLocalBeginDefaultShell - Uses the LocalToLocal VecScatter context set by the user to begin a local to local scatter
130: Collective
132: Input Arguments:
133: + dm - shell DM
134: . g - the original local vector
135: - mode - InsertMode
137: Output Parameter:
138: . l - the local vector with correct ghost values
140: Level: advanced
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.
144: .seealso: DMLocalToLocalEndDefaultShell()
145: @*/
146: PetscErrorCode DMLocalToLocalBeginDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
147: {
149: DM_Shell *shell = (DM_Shell*)dm->data;
152: if (!shell->ltol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToLocalVecScatter()");
153: VecScatterBegin(shell->ltol,g,l,mode,SCATTER_FORWARD);
154: return(0);
155: }
159: /*@
160: DMLocalToLocalEndDefaultShell - Uses the LocalToLocal VecScatter context set by the user to end a local to local scatter
161: Collective
163: Input Arguments:
164: + dm - shell DM
165: . g - the original local vector
166: - mode - InsertMode
168: Output Parameter:
169: . l - the local vector with correct ghost values
171: Level: advanced
173: .seealso: DMLocalToLocalBeginDefaultShell()
174: @*/
175: PetscErrorCode DMLocalToLocalEndDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
176: {
178: DM_Shell *shell = (DM_Shell*)dm->data;
181: if (!shell->ltol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
182: VecScatterEnd(shell->ltol,g,l,mode,SCATTER_FORWARD);
183: return(0);
184: }
188: static PetscErrorCode DMCreateMatrix_Shell(DM dm,Mat *J)
189: {
191: DM_Shell *shell = (DM_Shell*)dm->data;
192: Mat A;
197: if (!shell->A) {
198: if (shell->Xglobal) {
199: PetscInt m,M;
200: PetscInfo(dm,"Naively creating matrix using global vector distribution without preallocation");
201: VecGetSize(shell->Xglobal,&M);
202: VecGetLocalSize(shell->Xglobal,&m);
203: MatCreate(PetscObjectComm((PetscObject)dm),&shell->A);
204: MatSetSizes(shell->A,m,m,M,M);
205: MatSetType(shell->A,dm->mattype);
206: MatSetUp(shell->A);
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: PetscObjectTypeCompare((PetscObject)A,dm->mattype,&flg);
214: PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&seqaij);
215: PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&mpiaij);
216: PetscStrcmp(dm->mattype,MATAIJ,&aij);
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: PetscObjectReference((PetscObject)A);
223: MatZeroEntries(A);
224: *J = A;
225: } else { /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
226: MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,J);
227: MatZeroEntries(*J);
228: }
229: return(0);
230: }
234: PetscErrorCode DMCreateGlobalVector_Shell(DM dm,Vec *gvec)
235: {
237: DM_Shell *shell = (DM_Shell*)dm->data;
238: Vec X;
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: PetscObjectReference((PetscObject)X);
248: VecZeroEntries(X);
249: *gvec = X;
250: } else { /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
251: VecDuplicate(X,gvec);
252: VecZeroEntries(*gvec);
253: }
254: VecSetDM(*gvec,dm);
255: return(0);
256: }
260: PetscErrorCode DMCreateLocalVector_Shell(DM dm,Vec *gvec)
261: {
263: DM_Shell *shell = (DM_Shell*)dm->data;
264: Vec X;
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: PetscObjectReference((PetscObject)X);
274: VecZeroEntries(X);
275: *gvec = X;
276: } else { /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
277: VecDuplicate(X,gvec);
278: VecZeroEntries(*gvec);
279: }
280: VecSetDM(*gvec,dm);
281: return(0);
282: }
286: /*@
287: DMShellSetMatrix - sets a template matrix associated with the DMShell
289: Collective
291: Input Arguments:
292: + dm - shell DM
293: - J - template matrix
295: Level: advanced
297: .seealso: DMCreateMatrix(), DMShellSetCreateMatrix()
298: @*/
299: PetscErrorCode DMShellSetMatrix(DM dm,Mat J)
300: {
301: DM_Shell *shell = (DM_Shell*)dm->data;
303: PetscBool isshell;
308: PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
309: if (!isshell) return(0);
310: PetscObjectReference((PetscObject)J);
311: MatDestroy(&shell->A);
312: shell->A = J;
313: return(0);
314: }
318: /*@C
319: DMShellSetCreateMatrix - sets the routine to create a matrix associated with the shell DM
321: Logically Collective on DM
323: Input Arguments:
324: + dm - the shell DM
325: - func - the function to create a matrix
327: Level: advanced
329: .seealso: DMCreateMatrix(), DMShellSetMatrix()
330: @*/
331: PetscErrorCode DMShellSetCreateMatrix(DM dm,PetscErrorCode (*func)(DM,Mat*))
332: {
336: dm->ops->creatematrix = func;
337: return(0);
338: }
342: /*@
343: DMShellSetGlobalVector - sets a template global vector associated with the DMShell
345: Logically Collective on DM
347: Input Arguments:
348: + dm - shell DM
349: - X - template vector
351: Level: advanced
353: .seealso: DMCreateGlobalVector(), DMShellSetMatrix(), DMShellSetCreateGlobalVector()
354: @*/
355: PetscErrorCode DMShellSetGlobalVector(DM dm,Vec X)
356: {
357: DM_Shell *shell = (DM_Shell*)dm->data;
359: PetscBool isshell;
364: PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
365: if (!isshell) return(0);
366: PetscObjectReference((PetscObject)X);
367: VecDestroy(&shell->Xglobal);
368: shell->Xglobal = X;
369: return(0);
370: }
374: /*@C
375: DMShellSetCreateGlobalVector - sets the routine to create a global vector associated with the shell DM
377: Logically Collective
379: Input Arguments:
380: + dm - the shell DM
381: - func - the creation routine
383: Level: advanced
385: .seealso: DMShellSetGlobalVector(), DMShellSetCreateMatrix()
386: @*/
387: PetscErrorCode DMShellSetCreateGlobalVector(DM dm,PetscErrorCode (*func)(DM,Vec*))
388: {
392: dm->ops->createglobalvector = func;
393: return(0);
394: }
398: /*@
399: DMShellSetLocalVector - sets a template local vector associated with the DMShell
401: Logically Collective on DM
403: Input Arguments:
404: + dm - shell DM
405: - X - template vector
407: Level: advanced
409: .seealso: DMCreateLocalVector(), DMShellSetMatrix(), DMShellSetCreateLocalVector()
410: @*/
411: PetscErrorCode DMShellSetLocalVector(DM dm,Vec X)
412: {
413: DM_Shell *shell = (DM_Shell*)dm->data;
415: PetscBool isshell;
420: PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
421: if (!isshell) return(0);
422: PetscObjectReference((PetscObject)X);
423: VecDestroy(&shell->Xlocal);
424: shell->Xlocal = X;
425: return(0);
426: }
430: /*@C
431: DMShellSetCreateLocalVector - sets the routine to create a local vector associated with the shell DM
433: Logically Collective
435: Input Arguments:
436: + dm - the shell DM
437: - func - the creation routine
439: Level: advanced
441: .seealso: DMShellSetLocalVector(), DMShellSetCreateMatrix()
442: @*/
443: PetscErrorCode DMShellSetCreateLocalVector(DM dm,PetscErrorCode (*func)(DM,Vec*))
444: {
448: dm->ops->createlocalvector = func;
449: return(0);
450: }
454: /*@C
455: DMShellSetGlobalToLocal - Sets the routines used to perform a global to local scatter
457: Logically Collective on DM
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
464: Notes: If these functions are not provided but DMShellSetGlobalToLocalVecScatter() is called then
465: DMGlobalToLocalBeginDefaultShell()/DMGlobalToLocalEndDefaultShell() are used to to perform the transfers
467: Level: advanced
469: .seealso: DMShellSetLocalToGlobal(), DMGlobalToLocalBeginDefaultShell(), DMGlobalToLocalEndDefaultShell()
470: @*/
471: PetscErrorCode DMShellSetGlobalToLocal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) {
473: dm->ops->globaltolocalbegin = begin;
474: dm->ops->globaltolocalend = end;
475: return(0);
476: }
480: /*@C
481: DMShellSetLocalToGlobal - Sets the routines used to perform a local to global scatter
483: Logically Collective on DM
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
490: Notes: If these functions are not provided but DMShellSetLocalToGlobalVecScatter() is called then
491: DMLocalToGlobalBeginDefaultShell()/DMLocalToGlobalEndDefaultShell() are used to to perform the transfers
493: Level: advanced
495: .seealso: DMShellSetGlobalToLocal()
496: @*/
497: PetscErrorCode DMShellSetLocalToGlobal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) {
499: dm->ops->localtoglobalbegin = begin;
500: dm->ops->localtoglobalend = end;
501: return(0);
502: }
506: /*@C
507: DMShellSetLocalToLocal - Sets the routines used to perform a local to local scatter
509: Logically Collective on DM
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
516: Notes: If these functions are not provided but DMShellSetLocalToLocalVecScatter() is called then
517: DMLocalToLocalBeginDefaultShell()/DMLocalToLocalEndDefaultShell() are used to to perform the transfers
519: Level: advanced
521: .seealso: DMShellSetGlobalToLocal(), DMLocalToLocalBeginDefaultShell(), DMLocalToLocalEndDefaultShell()
522: @*/
523: PetscErrorCode DMShellSetLocalToLocal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) {
525: dm->ops->localtolocalbegin = begin;
526: dm->ops->localtolocalend = end;
527: return(0);
528: }
532: /*@
533: DMShellSetGlobalToLocalVecScatter - Sets a VecScatter context for global to local communication
535: Logically Collective on DM
537: Input Arguments
538: + dm - the shell DM
539: - gtol - the global to local VecScatter context
541: Level: advanced
543: .seealso: DMShellSetGlobalToLocal(), DMGlobalToLocalBeginDefaultShell(), DMGlobalToLocalEndDefaultShell()
544: @*/
545: PetscErrorCode DMShellSetGlobalToLocalVecScatter(DM dm, VecScatter gtol)
546: {
547: DM_Shell *shell = (DM_Shell*)dm->data;
551: PetscObjectReference((PetscObject)gtol);
552: /* Call VecScatterDestroy() to avoid a memory leak in case of re-setting. */
553: VecScatterDestroy(&shell->gtol);
554: shell->gtol = gtol;
555: return(0);
556: }
560: /*@
561: DMShellSetLocalToGlobalVecScatter - Sets a VecScatter context for local to global communication
563: Logically Collective on DM
565: Input Arguments
566: + dm - the shell DM
567: - ltog - the local to global VecScatter context
569: Level: advanced
571: .seealso: DMShellSetLocalToGlobal(), DMLocalToGlobalBeginDefaultShell(), DMLocalToGlobalEndDefaultShell()
572: @*/
573: PetscErrorCode DMShellSetLocalToGlobalVecScatter(DM dm, VecScatter ltog)
574: {
575: DM_Shell *shell = (DM_Shell*)dm->data;
579: PetscObjectReference((PetscObject)ltog);
580: /* Call VecScatterDestroy() to avoid a memory leak in case of re-setting. */
581: VecScatterDestroy(&shell->ltog);
582: shell->ltog = ltog;
583: return(0);
584: }
588: /*@
589: DMShellSetLocalToLocalVecScatter - Sets a VecScatter context for local to local communication
591: Logically Collective on DM
593: Input Arguments
594: + dm - the shell DM
595: - ltol - the local to local VecScatter context
597: Level: advanced
599: .seealso: DMShellSetLocalToLocal(), DMLocalToLocalBeginDefaultShell(), DMLocalToLocalEndDefaultShell()
600: @*/
601: PetscErrorCode DMShellSetLocalToLocalVecScatter(DM dm, VecScatter ltol)
602: {
603: DM_Shell *shell = (DM_Shell*)dm->data;
607: PetscObjectReference((PetscObject)ltol);
608: /* Call VecScatterDestroy() to avoid a memory leak in case of re-setting. */
609: VecScatterDestroy(&shell->ltol);
610: shell->ltol = ltol;
611: return(0);
612: }
616: static PetscErrorCode DMDestroy_Shell(DM dm)
617: {
619: DM_Shell *shell = (DM_Shell*)dm->data;
622: MatDestroy(&shell->A);
623: VecDestroy(&shell->Xglobal);
624: VecDestroy(&shell->Xlocal);
625: VecScatterDestroy(&shell->gtol);
626: VecScatterDestroy(&shell->ltog);
627: VecScatterDestroy(&shell->ltol);
628: /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
629: PetscFree(shell);
630: return(0);
631: }
635: static PetscErrorCode DMView_Shell(DM dm,PetscViewer v)
636: {
638: DM_Shell *shell = (DM_Shell*)dm->data;
641: VecView(shell->Xglobal,v);
642: return(0);
643: }
647: static PetscErrorCode DMLoad_Shell(DM dm,PetscViewer v)
648: {
650: DM_Shell *shell = (DM_Shell*)dm->data;
653: VecCreate(PetscObjectComm((PetscObject)dm),&shell->Xglobal);
654: VecLoad(shell->Xglobal,v);
655: return(0);
656: }
660: PetscErrorCode DMCreateSubDM_Shell(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm)
661: {
665: if (subdm) {DMShellCreate(PetscObjectComm((PetscObject) dm), subdm);}
666: DMCreateSubDM_Section_Private(dm, numFields, fields, is, subdm);
667: return(0);
668: }
672: PETSC_EXTERN PetscErrorCode DMCreate_Shell(DM dm)
673: {
675: DM_Shell *shell;
678: PetscNewLog(dm,&shell);
679: dm->data = shell;
681: PetscObjectChangeTypeName((PetscObject)dm,DMSHELL);
683: dm->ops->destroy = DMDestroy_Shell;
684: dm->ops->createglobalvector = DMCreateGlobalVector_Shell;
685: dm->ops->createlocalvector = DMCreateLocalVector_Shell;
686: dm->ops->creatematrix = DMCreateMatrix_Shell;
687: dm->ops->view = DMView_Shell;
688: dm->ops->load = DMLoad_Shell;
689: dm->ops->globaltolocalbegin = DMGlobalToLocalBeginDefaultShell;
690: dm->ops->globaltolocalend = DMGlobalToLocalEndDefaultShell;
691: dm->ops->localtoglobalbegin = DMLocalToGlobalBeginDefaultShell;
692: dm->ops->localtoglobalend = DMLocalToGlobalEndDefaultShell;
693: dm->ops->localtolocalbegin = DMLocalToLocalBeginDefaultShell;
694: dm->ops->localtolocalend = DMLocalToLocalEndDefaultShell;
695: dm->ops->createsubdm = DMCreateSubDM_Shell;
696: return(0);
697: }
701: /*@
702: DMShellCreate - Creates a shell DM object, used to manage user-defined problem data
704: Collective on MPI_Comm
706: Input Parameter:
707: . comm - the processors that will share the global vector
709: Output Parameters:
710: . shell - the shell DM
712: Level: advanced
714: .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateLocalVector()
715: @*/
716: PetscErrorCode DMShellCreate(MPI_Comm comm,DM *dm)
717: {
722: DMCreate(comm,dm);
723: DMSetType(*dm,DMSHELL);
724: DMSetUp(*dm);
725: return(0);
726: }