Actual source code: pack.c
petsc-3.5.4 2015-05-23
2: #include <../src/dm/impls/composite/packimpl.h> /*I "petscdmcomposite.h" I*/
3: #include <petscds.h>
7: /*@C
8: DMCompositeSetCoupling - Sets user provided routines that compute the coupling between the
9: seperate components (DMs) in a DMto build the correct matrix nonzero structure.
12: Logically Collective on MPI_Comm
14: Input Parameter:
15: + dm - the composite object
16: - formcouplelocations - routine to set the nonzero locations in the matrix
18: Level: advanced
20: Notes: See DMSetApplicationContext() and DMGetApplicationContext() for how to get user information into
21: this routine
23: @*/
24: PetscErrorCode DMCompositeSetCoupling(DM dm,PetscErrorCode (*FormCoupleLocations)(DM,Mat,PetscInt*,PetscInt*,PetscInt,PetscInt,PetscInt,PetscInt))
25: {
26: DM_Composite *com = (DM_Composite*)dm->data;
29: com->FormCoupleLocations = FormCoupleLocations;
30: return(0);
31: }
35: PetscErrorCode DMDestroy_Composite(DM dm)
36: {
37: PetscErrorCode ierr;
38: struct DMCompositeLink *next, *prev;
39: DM_Composite *com = (DM_Composite*)dm->data;
42: next = com->next;
43: while (next) {
44: prev = next;
45: next = next->next;
46: DMDestroy(&prev->dm);
47: PetscFree(prev->grstarts);
48: PetscFree(prev);
49: }
50: /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
51: PetscFree(com);
52: return(0);
53: }
57: PetscErrorCode DMView_Composite(DM dm,PetscViewer v)
58: {
60: PetscBool iascii;
61: DM_Composite *com = (DM_Composite*)dm->data;
64: PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERASCII,&iascii);
65: if (iascii) {
66: struct DMCompositeLink *lnk = com->next;
67: PetscInt i;
69: PetscViewerASCIIPrintf(v,"DM (%s)\n",((PetscObject)dm)->prefix ? ((PetscObject)dm)->prefix : "no prefix");
70: PetscViewerASCIIPrintf(v," contains %D DMs\n",com->nDM);
71: PetscViewerASCIIPushTab(v);
72: for (i=0; lnk; lnk=lnk->next,i++) {
73: PetscViewerASCIIPrintf(v,"Link %D: DM of type %s\n",i,((PetscObject)lnk->dm)->type_name);
74: PetscViewerASCIIPushTab(v);
75: DMView(lnk->dm,v);
76: PetscViewerASCIIPopTab(v);
77: }
78: PetscViewerASCIIPopTab(v);
79: }
80: return(0);
81: }
83: /* --------------------------------------------------------------------------------------*/
86: PetscErrorCode DMSetUp_Composite(DM dm)
87: {
88: PetscErrorCode ierr;
89: PetscInt nprev = 0;
90: PetscMPIInt rank,size;
91: DM_Composite *com = (DM_Composite*)dm->data;
92: struct DMCompositeLink *next = com->next;
93: PetscLayout map;
96: if (com->setup) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Packer has already been setup");
97: PetscLayoutCreate(PetscObjectComm((PetscObject)dm),&map);
98: PetscLayoutSetLocalSize(map,com->n);
99: PetscLayoutSetSize(map,PETSC_DETERMINE);
100: PetscLayoutSetBlockSize(map,1);
101: PetscLayoutSetUp(map);
102: PetscLayoutGetSize(map,&com->N);
103: PetscLayoutGetRange(map,&com->rstart,NULL);
104: PetscLayoutDestroy(&map);
106: /* now set the rstart for each linked vector */
107: MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);
108: MPI_Comm_size(PetscObjectComm((PetscObject)dm),&size);
109: while (next) {
110: next->rstart = nprev;
111: nprev += next->n;
112: next->grstart = com->rstart + next->rstart;
113: PetscMalloc1(size,&next->grstarts);
114: MPI_Allgather(&next->grstart,1,MPIU_INT,next->grstarts,1,MPIU_INT,PetscObjectComm((PetscObject)dm));
115: next = next->next;
116: }
117: com->setup = PETSC_TRUE;
118: return(0);
119: }
121: /* ----------------------------------------------------------------------------------*/
125: /*@
126: DMCompositeGetNumberDM - Get's the number of DM objects in the DMComposite
127: representation.
129: Not Collective
131: Input Parameter:
132: . dm - the packer object
134: Output Parameter:
135: . nDM - the number of DMs
137: Level: beginner
139: @*/
140: PetscErrorCode DMCompositeGetNumberDM(DM dm,PetscInt *nDM)
141: {
142: DM_Composite *com = (DM_Composite*)dm->data;
146: *nDM = com->nDM;
147: return(0);
148: }
153: /*@C
154: DMCompositeGetAccess - Allows one to access the individual packed vectors in their global
155: representation.
157: Collective on DMComposite
159: Input Parameters:
160: + dm - the packer object
161: - gvec - the global vector
163: Output Parameters:
164: . Vec* ... - the packed parallel vectors, NULL for those that are not needed
166: Notes: Use DMCompositeRestoreAccess() to return the vectors when you no longer need them
168: Fortran Notes:
170: Fortran callers must use numbered versions of this routine, e.g., DMCompositeGetAccess4(dm,gvec,vec1,vec2,vec3,vec4)
171: or use the alternative interface DMCompositeGetAccessArray().
173: Level: advanced
175: .seealso: DMCompositeGetEntries(), DMCompositeScatter()
176: @*/
177: PetscErrorCode DMCompositeGetAccess(DM dm,Vec gvec,...)
178: {
179: va_list Argp;
180: PetscErrorCode ierr;
181: struct DMCompositeLink *next;
182: DM_Composite *com = (DM_Composite*)dm->data;
187: next = com->next;
188: if (!com->setup) {
189: DMSetUp(dm);
190: }
192: /* loop over packed objects, handling one at at time */
193: va_start(Argp,gvec);
194: while (next) {
195: Vec *vec;
196: vec = va_arg(Argp, Vec*);
197: if (vec) {
198: PetscScalar *array;
199: DMGetGlobalVector(next->dm,vec);
200: VecGetArray(gvec,&array);
201: VecPlaceArray(*vec,array+next->rstart);
202: VecRestoreArray(gvec,&array);
203: }
204: next = next->next;
205: }
206: va_end(Argp);
207: return(0);
208: }
212: /*@C
213: DMCompositeGetAccessArray - Allows one to access the individual packed vectors in their global
214: representation.
216: Collective on DMComposite
218: Input Parameters:
219: + dm - the packer object
220: . pvec - packed vector
221: . nwanted - number of vectors wanted
222: - wanted - sorted array of vectors wanted, or NULL to get all vectors
224: Output Parameters:
225: . vecs - array of requested global vectors (must be allocated)
227: Notes: Use DMCompositeRestoreAccessArray() to return the vectors when you no longer need them
229: Level: advanced
231: .seealso: DMCompositeGetAccess(), DMCompositeGetEntries(), DMCompositeScatter(), DMCompositeGather()
232: @*/
233: PetscErrorCode DMCompositeGetAccessArray(DM dm,Vec pvec,PetscInt nwanted,const PetscInt *wanted,Vec *vecs)
234: {
235: PetscErrorCode ierr;
236: struct DMCompositeLink *link;
237: PetscInt i,wnum;
238: DM_Composite *com = (DM_Composite*)dm->data;
243: if (!com->setup) {
244: DMSetUp(dm);
245: }
247: for (i=0,wnum=0,link=com->next; link && wnum<nwanted; i++,link=link->next) {
248: if (!wanted || i == wanted[wnum]) {
249: PetscScalar *array;
250: Vec v;
251: DMGetGlobalVector(link->dm,&v);
252: VecGetArray(pvec,&array);
253: VecPlaceArray(v,array+link->rstart);
254: VecRestoreArray(pvec,&array);
255: vecs[wnum++] = v;
256: }
257: }
258: return(0);
259: }
263: /*@C
264: DMCompositeRestoreAccess - Returns the vectors obtained with DMCompositeGetAccess()
265: representation.
267: Collective on DMComposite
269: Input Parameters:
270: + dm - the packer object
271: . gvec - the global vector
272: - Vec* ... - the individual parallel vectors, NULL for those that are not needed
274: Level: advanced
276: .seealso DMCompositeAddDM(), DMCreateGlobalVector(),
277: DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeScatter(),
278: DMCompositeRestoreAccess(), DMCompositeGetAccess()
280: @*/
281: PetscErrorCode DMCompositeRestoreAccess(DM dm,Vec gvec,...)
282: {
283: va_list Argp;
284: PetscErrorCode ierr;
285: struct DMCompositeLink *next;
286: DM_Composite *com = (DM_Composite*)dm->data;
291: next = com->next;
292: if (!com->setup) {
293: DMSetUp(dm);
294: }
296: /* loop over packed objects, handling one at at time */
297: va_start(Argp,gvec);
298: while (next) {
299: Vec *vec;
300: vec = va_arg(Argp, Vec*);
301: if (vec) {
302: VecResetArray(*vec);
303: DMRestoreGlobalVector(next->dm,vec);
304: }
305: next = next->next;
306: }
307: va_end(Argp);
308: return(0);
309: }
313: /*@C
314: DMCompositeRestoreAccessArray - Returns the vectors obtained with DMCompositeGetAccessArray()
316: Collective on DMComposite
318: Input Parameters:
319: + dm - the packer object
320: . pvec - packed vector
321: . nwanted - number of vectors wanted
322: . wanted - sorted array of vectors wanted, or NULL to get all vectors
323: - vecs - array of global vectors to return
325: Level: advanced
327: .seealso: DMCompositeRestoreAccess(), DMCompositeRestoreEntries(), DMCompositeScatter(), DMCompositeGather()
328: @*/
329: PetscErrorCode DMCompositeRestoreAccessArray(DM dm,Vec pvec,PetscInt nwanted,const PetscInt *wanted,Vec *vecs)
330: {
331: PetscErrorCode ierr;
332: struct DMCompositeLink *link;
333: PetscInt i,wnum;
334: DM_Composite *com = (DM_Composite*)dm->data;
339: if (!com->setup) {
340: DMSetUp(dm);
341: }
343: for (i=0,wnum=0,link=com->next; link && wnum<nwanted; i++,link=link->next) {
344: if (!wanted || i == wanted[wnum]) {
345: VecResetArray(vecs[wnum]);
346: DMRestoreGlobalVector(link->dm,&vecs[wnum]);
347: wnum++;
348: }
349: }
350: return(0);
351: }
355: /*@C
356: DMCompositeScatter - Scatters from a global packed vector into its individual local vectors
358: Collective on DMComposite
360: Input Parameters:
361: + dm - the packer object
362: . gvec - the global vector
363: - Vec ... - the individual sequential vectors, NULL for those that are not needed
365: Level: advanced
367: Notes:
368: DMCompositeScatterArray() is a non-variadic alternative that is often more convenient for library callers and is
369: accessible from Fortran.
371: .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
372: DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
373: DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
374: DMCompositeScatterArray()
376: @*/
377: PetscErrorCode DMCompositeScatter(DM dm,Vec gvec,...)
378: {
379: va_list Argp;
380: PetscErrorCode ierr;
381: struct DMCompositeLink *next;
382: PetscInt cnt;
383: DM_Composite *com = (DM_Composite*)dm->data;
388: if (!com->setup) {
389: DMSetUp(dm);
390: }
392: /* loop over packed objects, handling one at at time */
393: va_start(Argp,gvec);
394: for (cnt=3,next=com->next; next; cnt++,next=next->next) {
395: Vec local;
396: local = va_arg(Argp, Vec);
397: if (local) {
398: Vec global;
399: PetscScalar *array;
401: DMGetGlobalVector(next->dm,&global);
402: VecGetArray(gvec,&array);
403: VecPlaceArray(global,array+next->rstart);
404: DMGlobalToLocalBegin(next->dm,global,INSERT_VALUES,local);
405: DMGlobalToLocalEnd(next->dm,global,INSERT_VALUES,local);
406: VecRestoreArray(gvec,&array);
407: VecResetArray(global);
408: DMRestoreGlobalVector(next->dm,&global);
409: }
410: }
411: va_end(Argp);
412: return(0);
413: }
417: /*@
418: DMCompositeScatterArray - Scatters from a global packed vector into its individual local vectors
420: Collective on DMComposite
422: Input Parameters:
423: + dm - the packer object
424: . gvec - the global vector
425: . lvecs - array of local vectors, NULL for any that are not needed
427: Level: advanced
429: Note:
430: This is a non-variadic alternative to DMCompositeScatterArray()
432: .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector()
433: DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
434: DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
436: @*/
437: PetscErrorCode DMCompositeScatterArray(DM dm,Vec gvec,Vec *lvecs)
438: {
439: PetscErrorCode ierr;
440: struct DMCompositeLink *next;
441: PetscInt i;
442: DM_Composite *com = (DM_Composite*)dm->data;
447: if (!com->setup) {
448: DMSetUp(dm);
449: }
451: /* loop over packed objects, handling one at at time */
452: for (i=0,next=com->next; next; next=next->next,i++) {
453: if (lvecs[i]) {
454: Vec global;
455: PetscScalar *array;
457: DMGetGlobalVector(next->dm,&global);
458: VecGetArray(gvec,&array);
459: VecPlaceArray(global,array+next->rstart);
460: DMGlobalToLocalBegin(next->dm,global,INSERT_VALUES,lvecs[i]);
461: DMGlobalToLocalEnd(next->dm,global,INSERT_VALUES,lvecs[i]);
462: VecRestoreArray(gvec,&array);
463: VecResetArray(global);
464: DMRestoreGlobalVector(next->dm,&global);
465: }
466: }
467: return(0);
468: }
472: /*@C
473: DMCompositeGather - Gathers into a global packed vector from its individual local vectors
475: Collective on DMComposite
477: Input Parameter:
478: + dm - the packer object
479: . gvec - the global vector
480: - Vec ... - the individual sequential vectors, NULL for any that are not needed
482: Level: advanced
484: .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
485: DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
486: DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
488: @*/
489: PetscErrorCode DMCompositeGather(DM dm,Vec gvec,InsertMode imode,...)
490: {
491: va_list Argp;
492: PetscErrorCode ierr;
493: struct DMCompositeLink *next;
494: DM_Composite *com = (DM_Composite*)dm->data;
495: PetscInt cnt;
500: if (!com->setup) {
501: DMSetUp(dm);
502: }
504: /* loop over packed objects, handling one at at time */
505: va_start(Argp,imode);
506: for (cnt=3,next=com->next; next; cnt++,next=next->next) {
507: Vec local;
508: local = va_arg(Argp, Vec);
509: if (local) {
510: PetscScalar *array;
511: Vec global;
513: DMGetGlobalVector(next->dm,&global);
514: VecGetArray(gvec,&array);
515: VecPlaceArray(global,array+next->rstart);
516: DMLocalToGlobalBegin(next->dm,local,imode,global);
517: DMLocalToGlobalEnd(next->dm,local,imode,global);
518: VecRestoreArray(gvec,&array);
519: VecResetArray(global);
520: DMRestoreGlobalVector(next->dm,&global);
521: }
522: }
523: va_end(Argp);
524: return(0);
525: }
529: /*@
530: DMCompositeGatherArray - Gathers into a global packed vector from its individual local vectors
532: Collective on DMComposite
534: Input Parameter:
535: + dm - the packer object
536: . gvec - the global vector
537: - lvecs - the individual sequential vectors, NULL for any that are not needed
539: Level: advanced
541: Notes:
542: This is a non-variadic alternative to DMCompositeGather().
544: .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
545: DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
546: DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries(),
547: @*/
548: PetscErrorCode DMCompositeGatherArray(DM dm,Vec gvec,InsertMode imode,Vec *lvecs)
549: {
550: PetscErrorCode ierr;
551: struct DMCompositeLink *next;
552: DM_Composite *com = (DM_Composite*)dm->data;
553: PetscInt i;
558: if (!com->setup) {
559: DMSetUp(dm);
560: }
562: /* loop over packed objects, handling one at at time */
563: for (next=com->next,i=0; next; next=next->next,i++) {
564: if (lvecs[i]) {
565: PetscScalar *array;
566: Vec global;
568: DMGetGlobalVector(next->dm,&global);
569: VecGetArray(gvec,&array);
570: VecPlaceArray(global,array+next->rstart);
571: DMLocalToGlobalBegin(next->dm,lvecs[i],imode,global);
572: DMLocalToGlobalEnd(next->dm,lvecs[i],imode,global);
573: VecRestoreArray(gvec,&array);
574: VecResetArray(global);
575: DMRestoreGlobalVector(next->dm,&global);
576: }
577: }
578: return(0);
579: }
583: /*@C
584: DMCompositeAddDM - adds a DM vector to a DMComposite
586: Collective on DMComposite
588: Input Parameter:
589: + dm - the packer object
590: - dm - the DM object, if the DM is a da you will need to caste it with a (DM)
592: Level: advanced
594: .seealso DMDestroy(), DMCompositeGather(), DMCompositeAddDM(), DMCreateGlobalVector(),
595: DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
596: DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
598: @*/
599: PetscErrorCode DMCompositeAddDM(DM dmc,DM dm)
600: {
601: PetscErrorCode ierr;
602: PetscInt n,nlocal;
603: struct DMCompositeLink *mine,*next;
604: Vec global,local;
605: DM_Composite *com = (DM_Composite*)dmc->data;
610: next = com->next;
611: if (com->setup) SETERRQ(PetscObjectComm((PetscObject)dmc),PETSC_ERR_ARG_WRONGSTATE,"Cannot add a DM once you have used the DMComposite");
613: /* create new link */
614: PetscNew(&mine);
615: PetscObjectReference((PetscObject)dm);
616: DMGetGlobalVector(dm,&global);
617: VecGetLocalSize(global,&n);
618: DMRestoreGlobalVector(dm,&global);
619: DMGetLocalVector(dm,&local);
620: VecGetSize(local,&nlocal);
621: DMRestoreLocalVector(dm,&local);
623: mine->n = n;
624: mine->nlocal = nlocal;
625: mine->dm = dm;
626: mine->next = NULL;
627: com->n += n;
629: /* add to end of list */
630: if (!next) com->next = mine;
631: else {
632: while (next->next) next = next->next;
633: next->next = mine;
634: }
635: com->nDM++;
636: com->nmine++;
637: return(0);
638: }
640: #include <petscdraw.h>
641: PETSC_EXTERN PetscErrorCode VecView_MPI(Vec,PetscViewer);
644: PetscErrorCode VecView_DMComposite(Vec gvec,PetscViewer viewer)
645: {
646: DM dm;
647: PetscErrorCode ierr;
648: struct DMCompositeLink *next;
649: PetscBool isdraw;
650: DM_Composite *com;
653: VecGetDM(gvec, &dm);
654: if (!dm) SETERRQ(PetscObjectComm((PetscObject)gvec),PETSC_ERR_ARG_WRONG,"Vector not generated from a DMComposite");
655: com = (DM_Composite*)dm->data;
656: next = com->next;
658: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
659: if (!isdraw) {
660: /* do I really want to call this? */
661: VecView_MPI(gvec,viewer);
662: } else {
663: PetscInt cnt = 0;
665: /* loop over packed objects, handling one at at time */
666: while (next) {
667: Vec vec;
668: PetscScalar *array;
669: PetscInt bs;
671: /* Should use VecGetSubVector() eventually, but would need to forward the DM for that to work */
672: DMGetGlobalVector(next->dm,&vec);
673: VecGetArray(gvec,&array);
674: VecPlaceArray(vec,array+next->rstart);
675: VecRestoreArray(gvec,&array);
676: VecView(vec,viewer);
677: VecGetBlockSize(vec,&bs);
678: VecResetArray(vec);
679: DMRestoreGlobalVector(next->dm,&vec);
680: PetscViewerDrawBaseAdd(viewer,bs);
681: cnt += bs;
682: next = next->next;
683: }
684: PetscViewerDrawBaseAdd(viewer,-cnt);
685: }
686: return(0);
687: }
691: PetscErrorCode DMCreateGlobalVector_Composite(DM dm,Vec *gvec)
692: {
694: DM_Composite *com = (DM_Composite*)dm->data;
698: DMSetUp(dm);
699: VecCreateMPI(PetscObjectComm((PetscObject)dm),com->n,com->N,gvec);
700: VecSetDM(*gvec, dm);
701: VecSetOperation(*gvec,VECOP_VIEW,(void (*)(void))VecView_DMComposite);
702: return(0);
703: }
707: PetscErrorCode DMCreateLocalVector_Composite(DM dm,Vec *lvec)
708: {
710: DM_Composite *com = (DM_Composite*)dm->data;
714: if (!com->setup) {
715: DMSetUp(dm);
716: }
717: VecCreateSeq(PetscObjectComm((PetscObject)dm),com->nghost,lvec);
718: VecSetDM(*lvec, dm);
719: return(0);
720: }
724: /*@C
725: DMCompositeGetISLocalToGlobalMappings - gets an ISLocalToGlobalMapping for each DM in the DMComposite, maps to the composite global space
727: Collective on DM
729: Input Parameter:
730: . dm - the packer object
732: Output Parameters:
733: . ltogs - the individual mappings for each packed vector. Note that this includes
734: all the ghost points that individual ghosted DMDA's may have.
736: Level: advanced
738: Notes:
739: Each entry of ltogs should be destroyed with ISLocalToGlobalMappingDestroy(), the ltogs array should be freed with PetscFree().
741: .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
742: DMCompositeGather(), DMCompositeCreate(), DMCompositeGetAccess(), DMCompositeScatter(),
743: DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(),DMCompositeGetEntries()
745: @*/
746: PetscErrorCode DMCompositeGetISLocalToGlobalMappings(DM dm,ISLocalToGlobalMapping **ltogs)
747: {
748: PetscErrorCode ierr;
749: PetscInt i,*idx,n,cnt;
750: struct DMCompositeLink *next;
751: PetscMPIInt rank;
752: DM_Composite *com = (DM_Composite*)dm->data;
756: DMSetUp(dm);
757: PetscMalloc1((com->nDM),ltogs);
758: next = com->next;
759: MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);
761: /* loop over packed objects, handling one at at time */
762: cnt = 0;
763: while (next) {
764: ISLocalToGlobalMapping ltog;
765: PetscMPIInt size;
766: const PetscInt *suboff,*indices;
767: Vec global;
769: /* Get sub-DM global indices for each local dof */
770: DMGetLocalToGlobalMapping(next->dm,<og);
771: ISLocalToGlobalMappingGetSize(ltog,&n);
772: ISLocalToGlobalMappingGetIndices(ltog,&indices);
773: PetscMalloc1(n,&idx);
775: /* Get the offsets for the sub-DM global vector */
776: DMGetGlobalVector(next->dm,&global);
777: VecGetOwnershipRanges(global,&suboff);
778: MPI_Comm_size(PetscObjectComm((PetscObject)global),&size);
780: /* Shift the sub-DM definition of the global space to the composite global space */
781: for (i=0; i<n; i++) {
782: PetscInt subi = indices[i],lo = 0,hi = size,t;
783: /* Binary search to find which rank owns subi */
784: while (hi-lo > 1) {
785: t = lo + (hi-lo)/2;
786: if (suboff[t] > subi) hi = t;
787: else lo = t;
788: }
789: idx[i] = subi - suboff[lo] + next->grstarts[lo];
790: }
791: ISLocalToGlobalMappingRestoreIndices(ltog,&indices);
792: ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm),1,n,idx,PETSC_OWN_POINTER,&(*ltogs)[cnt]);
793: DMRestoreGlobalVector(next->dm,&global);
794: next = next->next;
795: cnt++;
796: }
797: return(0);
798: }
802: /*@C
803: DMCompositeGetLocalISs - Gets index sets for each component of a composite local vector
805: Not Collective
807: Input Arguments:
808: . dm - composite DM
810: Output Arguments:
811: . is - array of serial index sets for each each component of the DMComposite
813: Level: intermediate
815: Notes:
816: At present, a composite local vector does not normally exist. This function is used to provide index sets for
817: MatGetLocalSubMatrix(). In the future, the scatters for each entry in the DMComposite may be be merged into a single
818: scatter to a composite local vector. The user should not typically need to know which is being done.
820: To get the composite global indices at all local points (including ghosts), use DMCompositeGetISLocalToGlobalMappings().
822: To get index sets for pieces of the composite global vector, use DMCompositeGetGlobalISs().
824: Each returned IS should be destroyed with ISDestroy(), the array should be freed with PetscFree().
826: .seealso: DMCompositeGetGlobalISs(), DMCompositeGetISLocalToGlobalMappings(), MatGetLocalSubMatrix(), MatCreateLocalRef()
827: @*/
828: PetscErrorCode DMCompositeGetLocalISs(DM dm,IS **is)
829: {
830: PetscErrorCode ierr;
831: DM_Composite *com = (DM_Composite*)dm->data;
832: struct DMCompositeLink *link;
833: PetscInt cnt,start;
838: PetscMalloc1(com->nmine,is);
839: for (cnt=0,start=0,link=com->next; link; start+=link->nlocal,cnt++,link=link->next) {
840: PetscInt bs;
841: ISCreateStride(PETSC_COMM_SELF,link->nlocal,start,1,&(*is)[cnt]);
842: DMGetBlockSize(link->dm,&bs);
843: ISSetBlockSize((*is)[cnt],bs);
844: }
845: return(0);
846: }
850: /*@C
851: DMCompositeGetGlobalISs - Gets the index sets for each composed object
853: Collective on DMComposite
855: Input Parameter:
856: . dm - the packer object
858: Output Parameters:
859: . is - the array of index sets
861: Level: advanced
863: Notes:
864: The is entries should be destroyed with ISDestroy(), the is array should be freed with PetscFree()
866: These could be used to extract a subset of vector entries for a "multi-physics" preconditioner
868: Use DMCompositeGetLocalISs() for index sets in the packed local numbering, and
869: DMCompositeGetISLocalToGlobalMappings() for to map local sub-DM (including ghost) indices to packed global
870: indices.
872: .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
873: DMCompositeGather(), DMCompositeCreate(), DMCompositeGetAccess(), DMCompositeScatter(),
874: DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(),DMCompositeGetEntries()
876: @*/
878: PetscErrorCode DMCompositeGetGlobalISs(DM dm,IS *is[])
879: {
880: PetscErrorCode ierr;
881: PetscInt cnt = 0;
882: struct DMCompositeLink *next;
883: PetscMPIInt rank;
884: DM_Composite *com = (DM_Composite*)dm->data;
888: PetscMalloc1((com->nDM),is);
889: next = com->next;
890: MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);
892: /* loop over packed objects, handling one at at time */
893: while (next) {
894: ISCreateStride(PetscObjectComm((PetscObject)dm),next->n,next->grstart,1,&(*is)[cnt]);
895: if (dm->prob) {
896: MatNullSpace space;
897: Mat pmat;
898: PetscObject disc;
899: PetscInt Nf;
901: PetscDSGetNumFields(dm->prob, &Nf);
902: if (cnt < Nf) {
903: PetscDSGetDiscretization(dm->prob, cnt, &disc);
904: PetscObjectQuery(disc, "nullspace", (PetscObject*) &space);
905: if (space) {PetscObjectCompose((PetscObject) (*is)[cnt], "nullspace", (PetscObject) space);}
906: PetscObjectQuery(disc, "nearnullspace", (PetscObject*) &space);
907: if (space) {PetscObjectCompose((PetscObject) (*is)[cnt], "nearnullspace", (PetscObject) space);}
908: PetscObjectQuery(disc, "pmat", (PetscObject*) &pmat);
909: if (pmat) {PetscObjectCompose((PetscObject) (*is)[cnt], "pmat", (PetscObject) pmat);}
910: }
911: }
912: cnt++;
913: next = next->next;
914: }
915: return(0);
916: }
920: PetscErrorCode DMCreateFieldIS_Composite(DM dm, PetscInt *numFields,char ***fieldNames, IS **fields)
921: {
922: PetscInt nDM;
923: DM *dms;
924: PetscInt i;
928: DMCompositeGetNumberDM(dm, &nDM);
929: if (numFields) *numFields = nDM;
930: DMCompositeGetGlobalISs(dm, fields);
931: if (fieldNames) {
932: PetscMalloc1(nDM, &dms);
933: PetscMalloc1(nDM, fieldNames);
934: DMCompositeGetEntriesArray(dm, dms);
935: for (i=0; i<nDM; i++) {
936: char buf[256];
937: const char *splitname;
939: /* Split naming precedence: object name, prefix, number */
940: splitname = ((PetscObject) dm)->name;
941: if (!splitname) {
942: PetscObjectGetOptionsPrefix((PetscObject)dms[i],&splitname);
943: if (splitname) {
944: size_t len;
945: PetscStrncpy(buf,splitname,sizeof(buf));
946: buf[sizeof(buf) - 1] = 0;
947: PetscStrlen(buf,&len);
948: if (buf[len-1] == '_') buf[len-1] = 0; /* Remove trailing underscore if it was used */
949: splitname = buf;
950: }
951: }
952: if (!splitname) {
953: PetscSNPrintf(buf,sizeof(buf),"%D",i);
954: splitname = buf;
955: }
956: PetscStrallocpy(splitname,&(*fieldNames)[i]);
957: }
958: PetscFree(dms);
959: }
960: return(0);
961: }
963: /*
964: This could take over from DMCreateFieldIS(), as it is more general,
965: making DMCreateFieldIS() a special case -- calling with dmlist == NULL;
966: At this point it's probably best to be less intrusive, however.
967: */
970: PetscErrorCode DMCreateFieldDecomposition_Composite(DM dm, PetscInt *len,char ***namelist, IS **islist, DM **dmlist)
971: {
972: PetscInt nDM;
973: PetscInt i;
977: DMCreateFieldIS_Composite(dm, len, namelist, islist);
978: if (dmlist) {
979: DMCompositeGetNumberDM(dm, &nDM);
980: PetscMalloc1(nDM, dmlist);
981: DMCompositeGetEntriesArray(dm, *dmlist);
982: for (i=0; i<nDM; i++) {
983: PetscObjectReference((PetscObject)((*dmlist)[i]));
984: }
985: }
986: return(0);
987: }
991: /* -------------------------------------------------------------------------------------*/
994: /*@C
995: DMCompositeGetLocalVectors - Gets local vectors for each part of a DMComposite.
996: Use DMCompositeRestoreLocalVectors() to return them.
998: Not Collective
1000: Input Parameter:
1001: . dm - the packer object
1003: Output Parameter:
1004: . Vec ... - the individual sequential Vecs
1006: Level: advanced
1008: .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
1009: DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
1010: DMCompositeRestoreLocalVectors(), DMCompositeScatter(), DMCompositeGetEntries()
1012: @*/
1013: PetscErrorCode DMCompositeGetLocalVectors(DM dm,...)
1014: {
1015: va_list Argp;
1016: PetscErrorCode ierr;
1017: struct DMCompositeLink *next;
1018: DM_Composite *com = (DM_Composite*)dm->data;
1022: next = com->next;
1023: /* loop over packed objects, handling one at at time */
1024: va_start(Argp,dm);
1025: while (next) {
1026: Vec *vec;
1027: vec = va_arg(Argp, Vec*);
1028: if (vec) {DMGetLocalVector(next->dm,vec);}
1029: next = next->next;
1030: }
1031: va_end(Argp);
1032: return(0);
1033: }
1037: /*@C
1038: DMCompositeRestoreLocalVectors - Restores local vectors for each part of a DMComposite.
1040: Not Collective
1042: Input Parameter:
1043: . dm - the packer object
1045: Output Parameter:
1046: . Vec ... - the individual sequential Vecs
1048: Level: advanced
1050: .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
1051: DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
1052: DMCompositeGetLocalVectors(), DMCompositeScatter(), DMCompositeGetEntries()
1054: @*/
1055: PetscErrorCode DMCompositeRestoreLocalVectors(DM dm,...)
1056: {
1057: va_list Argp;
1058: PetscErrorCode ierr;
1059: struct DMCompositeLink *next;
1060: DM_Composite *com = (DM_Composite*)dm->data;
1064: next = com->next;
1065: /* loop over packed objects, handling one at at time */
1066: va_start(Argp,dm);
1067: while (next) {
1068: Vec *vec;
1069: vec = va_arg(Argp, Vec*);
1070: if (vec) {DMRestoreLocalVector(next->dm,vec);}
1071: next = next->next;
1072: }
1073: va_end(Argp);
1074: return(0);
1075: }
1077: /* -------------------------------------------------------------------------------------*/
1080: /*@C
1081: DMCompositeGetEntries - Gets the DM for each entry in a DMComposite.
1083: Not Collective
1085: Input Parameter:
1086: . dm - the packer object
1088: Output Parameter:
1089: . DM ... - the individual entries (DMs)
1091: Level: advanced
1093: .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(), DMCompositeGetEntriesArray()
1094: DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
1095: DMCompositeRestoreLocalVectors(), DMCompositeGetLocalVectors(), DMCompositeScatter(),
1096: DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors()
1098: @*/
1099: PetscErrorCode DMCompositeGetEntries(DM dm,...)
1100: {
1101: va_list Argp;
1102: struct DMCompositeLink *next;
1103: DM_Composite *com = (DM_Composite*)dm->data;
1107: next = com->next;
1108: /* loop over packed objects, handling one at at time */
1109: va_start(Argp,dm);
1110: while (next) {
1111: DM *dmn;
1112: dmn = va_arg(Argp, DM*);
1113: if (dmn) *dmn = next->dm;
1114: next = next->next;
1115: }
1116: va_end(Argp);
1117: return(0);
1118: }
1122: /*@C
1123: DMCompositeGetEntriesArray - Gets the DM for each entry in a DMComposite.
1125: Not Collective
1127: Input Parameter:
1128: + dm - the packer object
1129: - dms - array of sufficient length (see DMCompositeGetNumberDM()), holds the DMs on output
1131: Level: advanced
1133: .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(), DMCompositeGetEntries()
1134: DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
1135: DMCompositeRestoreLocalVectors(), DMCompositeGetLocalVectors(), DMCompositeScatter(),
1136: DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors()
1138: @*/
1139: PetscErrorCode DMCompositeGetEntriesArray(DM dm,DM dms[])
1140: {
1141: struct DMCompositeLink *next;
1142: DM_Composite *com = (DM_Composite*)dm->data;
1143: PetscInt i;
1147: /* loop over packed objects, handling one at at time */
1148: for (next=com->next,i=0; next; next=next->next,i++) dms[i] = next->dm;
1149: return(0);
1150: }
1154: PetscErrorCode DMRefine_Composite(DM dmi,MPI_Comm comm,DM *fine)
1155: {
1156: PetscErrorCode ierr;
1157: struct DMCompositeLink *next;
1158: DM_Composite *com = (DM_Composite*)dmi->data;
1159: DM dm;
1163: if (comm == MPI_COMM_NULL) {
1164: PetscObjectGetComm((PetscObject)dmi,&comm);
1165: }
1166: DMSetUp(dmi);
1167: next = com->next;
1168: DMCompositeCreate(comm,fine);
1170: /* loop over packed objects, handling one at at time */
1171: while (next) {
1172: DMRefine(next->dm,comm,&dm);
1173: DMCompositeAddDM(*fine,dm);
1174: PetscObjectDereference((PetscObject)dm);
1175: next = next->next;
1176: }
1177: return(0);
1178: }
1182: PetscErrorCode DMCoarsen_Composite(DM dmi,MPI_Comm comm,DM *fine)
1183: {
1184: PetscErrorCode ierr;
1185: struct DMCompositeLink *next;
1186: DM_Composite *com = (DM_Composite*)dmi->data;
1187: DM dm;
1191: DMSetUp(dmi);
1192: if (comm == MPI_COMM_NULL) {
1193: PetscObjectGetComm((PetscObject)dmi,&comm);
1194: }
1195: next = com->next;
1196: DMCompositeCreate(comm,fine);
1198: /* loop over packed objects, handling one at at time */
1199: while (next) {
1200: DMCoarsen(next->dm,comm,&dm);
1201: DMCompositeAddDM(*fine,dm);
1202: PetscObjectDereference((PetscObject)dm);
1203: next = next->next;
1204: }
1205: return(0);
1206: }
1210: PetscErrorCode DMCreateInterpolation_Composite(DM coarse,DM fine,Mat *A,Vec *v)
1211: {
1212: PetscErrorCode ierr;
1213: PetscInt m,n,M,N,nDM,i;
1214: struct DMCompositeLink *nextc;
1215: struct DMCompositeLink *nextf;
1216: Vec gcoarse,gfine,*vecs;
1217: DM_Composite *comcoarse = (DM_Composite*)coarse->data;
1218: DM_Composite *comfine = (DM_Composite*)fine->data;
1219: Mat *mats;
1224: DMSetUp(coarse);
1225: DMSetUp(fine);
1226: /* use global vectors only for determining matrix layout */
1227: DMGetGlobalVector(coarse,&gcoarse);
1228: DMGetGlobalVector(fine,&gfine);
1229: VecGetLocalSize(gcoarse,&n);
1230: VecGetLocalSize(gfine,&m);
1231: VecGetSize(gcoarse,&N);
1232: VecGetSize(gfine,&M);
1233: DMRestoreGlobalVector(coarse,&gcoarse);
1234: DMRestoreGlobalVector(fine,&gfine);
1236: nDM = comfine->nDM;
1237: if (nDM != comcoarse->nDM) SETERRQ2(PetscObjectComm((PetscObject)fine),PETSC_ERR_ARG_INCOMP,"Fine DMComposite has %D entries, but coarse has %D",nDM,comcoarse->nDM);
1238: PetscCalloc1(nDM*nDM,&mats);
1239: if (v) {
1240: PetscCalloc1(nDM,&vecs);
1241: }
1243: /* loop over packed objects, handling one at at time */
1244: for (nextc=comcoarse->next,nextf=comfine->next,i=0; nextc; nextc=nextc->next,nextf=nextf->next,i++) {
1245: if (!v) {
1246: DMCreateInterpolation(nextc->dm,nextf->dm,&mats[i*nDM+i],NULL);
1247: } else {
1248: DMCreateInterpolation(nextc->dm,nextf->dm,&mats[i*nDM+i],&vecs[i]);
1249: }
1250: }
1251: MatCreateNest(PetscObjectComm((PetscObject)fine),nDM,NULL,nDM,NULL,mats,A);
1252: if (v) {
1253: VecCreateNest(PetscObjectComm((PetscObject)fine),nDM,NULL,vecs,v);
1254: }
1255: for (i=0; i<nDM*nDM; i++) {MatDestroy(&mats[i]);}
1256: PetscFree(mats);
1257: if (v) {
1258: for (i=0; i<nDM; i++) {VecDestroy(&vecs[i]);}
1259: PetscFree(vecs);
1260: }
1261: return(0);
1262: }
1266: static PetscErrorCode DMGetLocalToGlobalMapping_Composite(DM dm)
1267: {
1268: DM_Composite *com = (DM_Composite*)dm->data;
1269: ISLocalToGlobalMapping *ltogs;
1270: PetscInt i;
1271: PetscErrorCode ierr;
1274: /* Set the ISLocalToGlobalMapping on the new matrix */
1275: DMCompositeGetISLocalToGlobalMappings(dm,<ogs);
1276: ISLocalToGlobalMappingConcatenate(PetscObjectComm((PetscObject)dm),com->nDM,ltogs,&dm->ltogmap);
1277: for (i=0; i<com->nDM; i++) {ISLocalToGlobalMappingDestroy(<ogs[i]);}
1278: PetscFree(ltogs);
1279: return(0);
1280: }
1285: PetscErrorCode DMCreateColoring_Composite(DM dm,ISColoringType ctype,ISColoring *coloring)
1286: {
1287: PetscErrorCode ierr;
1288: PetscInt n,i,cnt;
1289: ISColoringValue *colors;
1290: PetscBool dense = PETSC_FALSE;
1291: ISColoringValue maxcol = 0;
1292: DM_Composite *com = (DM_Composite*)dm->data;
1296: if (ctype == IS_COLORING_GHOSTED) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only global coloring supported");
1297: else if (ctype == IS_COLORING_GLOBAL) {
1298: n = com->n;
1299: } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Unknown ISColoringType");
1300: PetscMalloc1(n,&colors); /* freed in ISColoringDestroy() */
1302: PetscOptionsGetBool(NULL,"-dmcomposite_dense_jacobian",&dense,NULL);
1303: if (dense) {
1304: for (i=0; i<n; i++) {
1305: colors[i] = (ISColoringValue)(com->rstart + i);
1306: }
1307: maxcol = com->N;
1308: } else {
1309: struct DMCompositeLink *next = com->next;
1310: PetscMPIInt rank;
1312: MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);
1313: cnt = 0;
1314: while (next) {
1315: ISColoring lcoloring;
1317: DMCreateColoring(next->dm,IS_COLORING_GLOBAL,&lcoloring);
1318: for (i=0; i<lcoloring->N; i++) {
1319: colors[cnt++] = maxcol + lcoloring->colors[i];
1320: }
1321: maxcol += lcoloring->n;
1322: ISColoringDestroy(&lcoloring);
1323: next = next->next;
1324: }
1325: }
1326: ISColoringCreate(PetscObjectComm((PetscObject)dm),maxcol,n,colors,coloring);
1327: return(0);
1328: }
1332: PetscErrorCode DMGlobalToLocalBegin_Composite(DM dm,Vec gvec,InsertMode mode,Vec lvec)
1333: {
1334: PetscErrorCode ierr;
1335: struct DMCompositeLink *next;
1336: PetscInt cnt = 3;
1337: PetscMPIInt rank;
1338: PetscScalar *garray,*larray;
1339: DM_Composite *com = (DM_Composite*)dm->data;
1344: next = com->next;
1345: if (!com->setup) {
1346: DMSetUp(dm);
1347: }
1348: MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);
1349: VecGetArray(gvec,&garray);
1350: VecGetArray(lvec,&larray);
1352: /* loop over packed objects, handling one at at time */
1353: while (next) {
1354: Vec local,global;
1355: PetscInt N;
1357: DMGetGlobalVector(next->dm,&global);
1358: VecGetLocalSize(global,&N);
1359: VecPlaceArray(global,garray);
1360: DMGetLocalVector(next->dm,&local);
1361: VecPlaceArray(local,larray);
1362: DMGlobalToLocalBegin(next->dm,global,mode,local);
1363: DMGlobalToLocalEnd(next->dm,global,mode,local);
1364: VecResetArray(global);
1365: VecResetArray(local);
1366: DMRestoreGlobalVector(next->dm,&global);
1367: DMRestoreGlobalVector(next->dm,&local);
1368: cnt++;
1369: larray += next->nlocal;
1370: next = next->next;
1371: }
1373: VecRestoreArray(gvec,NULL);
1374: VecRestoreArray(lvec,NULL);
1375: return(0);
1376: }
1380: PetscErrorCode DMGlobalToLocalEnd_Composite(DM dm,Vec gvec,InsertMode mode,Vec lvec)
1381: {
1383: return(0);
1384: }
1386: /*MC
1387: DMCOMPOSITE = "composite" - A DM object that is used to manage data for a collection of DMs
1389: Level: intermediate
1391: .seealso: DMType, DMCOMPOSITE, DMDACreate(), DMCreate(), DMSetType(), DMCompositeCreate()
1392: M*/
1397: PETSC_EXTERN PetscErrorCode DMCreate_Composite(DM p)
1398: {
1400: DM_Composite *com;
1403: PetscNewLog(p,&com);
1404: p->data = com;
1405: PetscObjectChangeTypeName((PetscObject)p,"DMComposite");
1406: com->n = 0;
1407: com->next = NULL;
1408: com->nDM = 0;
1410: p->ops->createglobalvector = DMCreateGlobalVector_Composite;
1411: p->ops->createlocalvector = DMCreateLocalVector_Composite;
1412: p->ops->getlocaltoglobalmapping = DMGetLocalToGlobalMapping_Composite;
1413: p->ops->createfieldis = DMCreateFieldIS_Composite;
1414: p->ops->createfielddecomposition = DMCreateFieldDecomposition_Composite;
1415: p->ops->refine = DMRefine_Composite;
1416: p->ops->coarsen = DMCoarsen_Composite;
1417: p->ops->createinterpolation = DMCreateInterpolation_Composite;
1418: p->ops->creatematrix = DMCreateMatrix_Composite;
1419: p->ops->getcoloring = DMCreateColoring_Composite;
1420: p->ops->globaltolocalbegin = DMGlobalToLocalBegin_Composite;
1421: p->ops->globaltolocalend = DMGlobalToLocalEnd_Composite;
1422: p->ops->destroy = DMDestroy_Composite;
1423: p->ops->view = DMView_Composite;
1424: p->ops->setup = DMSetUp_Composite;
1425: return(0);
1426: }
1430: /*@C
1431: DMCompositeCreate - Creates a vector packer, used to generate "composite"
1432: vectors made up of several subvectors.
1434: Collective on MPI_Comm
1436: Input Parameter:
1437: . comm - the processors that will share the global vector
1439: Output Parameters:
1440: . packer - the packer object
1442: Level: advanced
1444: .seealso DMDestroy(), DMCompositeAddDM(), DMCompositeScatter(),
1445: DMCompositeGather(), DMCreateGlobalVector(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess()
1446: DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
1448: @*/
1449: PetscErrorCode DMCompositeCreate(MPI_Comm comm,DM *packer)
1450: {
1455: DMCreate(comm,packer);
1456: DMSetType(*packer,DMCOMPOSITE);
1457: return(0);
1458: }