xref: /petsc/src/dm/impls/composite/pack.c (revision 82f516cc2a80c5c0e712e5bfc0bf40989ffef740)
1 
2 #include <../src/dm/impls/composite/packimpl.h>       /*I  "petscdmcomposite.h"  I*/
3 
4 #undef __FUNCT__
5 #define __FUNCT__ "DMCompositeSetCoupling"
6 /*@C
7     DMCompositeSetCoupling - Sets user provided routines that compute the coupling between the
8       seperate components (DMs) in a DMto build the correct matrix nonzero structure.
9 
10 
11     Logically Collective on MPI_Comm
12 
13     Input Parameter:
14 +   dm - the composite object
15 -   formcouplelocations - routine to set the nonzero locations in the matrix
16 
17     Level: advanced
18 
19     Notes: See DMSetApplicationContext() and DMGetApplicationContext() for how to get user information into
20         this routine
21 
22 @*/
23 PetscErrorCode  DMCompositeSetCoupling(DM dm,PetscErrorCode (*FormCoupleLocations)(DM,Mat,PetscInt*,PetscInt*,PetscInt,PetscInt,PetscInt,PetscInt))
24 {
25   DM_Composite *com = (DM_Composite*)dm->data;
26 
27   PetscFunctionBegin;
28   com->FormCoupleLocations = FormCoupleLocations;
29   PetscFunctionReturn(0);
30 }
31 
32 #undef __FUNCT__
33 #define __FUNCT__ "DMDestroy_Composite"
34 PetscErrorCode  DMDestroy_Composite(DM dm)
35 {
36   PetscErrorCode         ierr;
37   struct DMCompositeLink *next, *prev;
38   DM_Composite           *com = (DM_Composite*)dm->data;
39 
40   PetscFunctionBegin;
41   next = com->next;
42   while (next) {
43     prev = next;
44     next = next->next;
45     ierr = DMDestroy(&prev->dm);CHKERRQ(ierr);
46     ierr = PetscFree(prev->grstarts);CHKERRQ(ierr);
47     ierr = PetscFree(prev);CHKERRQ(ierr);
48   }
49   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
50   ierr = PetscFree(com);CHKERRQ(ierr);
51   PetscFunctionReturn(0);
52 }
53 
54 #undef __FUNCT__
55 #define __FUNCT__ "DMView_Composite"
56 PetscErrorCode  DMView_Composite(DM dm,PetscViewer v)
57 {
58   PetscErrorCode ierr;
59   PetscBool      iascii;
60   DM_Composite   *com = (DM_Composite*)dm->data;
61 
62   PetscFunctionBegin;
63   ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
64   if (iascii) {
65     struct DMCompositeLink *lnk = com->next;
66     PetscInt               i;
67 
68     ierr = PetscViewerASCIIPrintf(v,"DM (%s)\n",((PetscObject)dm)->prefix ? ((PetscObject)dm)->prefix : "no prefix");CHKERRQ(ierr);
69     ierr = PetscViewerASCIIPrintf(v,"  contains %D DMs\n",com->nDM);CHKERRQ(ierr);
70     ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr);
71     for (i=0; lnk; lnk=lnk->next,i++) {
72       ierr = PetscViewerASCIIPrintf(v,"Link %D: DM of type %s\n",i,((PetscObject)lnk->dm)->type_name);CHKERRQ(ierr);
73       ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr);
74       ierr = DMView(lnk->dm,v);CHKERRQ(ierr);
75       ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr);
76     }
77     ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr);
78   }
79   PetscFunctionReturn(0);
80 }
81 
82 /* --------------------------------------------------------------------------------------*/
83 #undef __FUNCT__
84 #define __FUNCT__ "DMSetUp_Composite"
85 PetscErrorCode  DMSetUp_Composite(DM dm)
86 {
87   PetscErrorCode         ierr;
88   PetscInt               nprev = 0;
89   PetscMPIInt            rank,size;
90   DM_Composite           *com  = (DM_Composite*)dm->data;
91   struct DMCompositeLink *next = com->next;
92   PetscLayout            map;
93 
94   PetscFunctionBegin;
95   if (com->setup) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Packer has already been setup");
96   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)dm),&map);CHKERRQ(ierr);
97   ierr = PetscLayoutSetLocalSize(map,com->n);CHKERRQ(ierr);
98   ierr = PetscLayoutSetSize(map,PETSC_DETERMINE);CHKERRQ(ierr);
99   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
100   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
101   ierr = PetscLayoutGetSize(map,&com->N);CHKERRQ(ierr);
102   ierr = PetscLayoutGetRange(map,&com->rstart,NULL);CHKERRQ(ierr);
103   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
104 
105   /* now set the rstart for each linked vector */
106   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
107   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm),&size);CHKERRQ(ierr);
108   while (next) {
109     next->rstart  = nprev;
110     nprev        += next->n;
111     next->grstart = com->rstart + next->rstart;
112     ierr          = PetscMalloc(size*sizeof(PetscInt),&next->grstarts);CHKERRQ(ierr);
113     ierr          = MPI_Allgather(&next->grstart,1,MPIU_INT,next->grstarts,1,MPIU_INT,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
114     next          = next->next;
115   }
116   com->setup = PETSC_TRUE;
117   PetscFunctionReturn(0);
118 }
119 
120 /* ----------------------------------------------------------------------------------*/
121 
122 #undef __FUNCT__
123 #define __FUNCT__ "DMCompositeGetNumberDM"
124 /*@
125     DMCompositeGetNumberDM - Get's the number of DM objects in the DMComposite
126        representation.
127 
128     Not Collective
129 
130     Input Parameter:
131 .    dm - the packer object
132 
133     Output Parameter:
134 .     nDM - the number of DMs
135 
136     Level: beginner
137 
138 @*/
139 PetscErrorCode  DMCompositeGetNumberDM(DM dm,PetscInt *nDM)
140 {
141   DM_Composite *com = (DM_Composite*)dm->data;
142 
143   PetscFunctionBegin;
144   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
145   *nDM = com->nDM;
146   PetscFunctionReturn(0);
147 }
148 
149 
150 #undef __FUNCT__
151 #define __FUNCT__ "DMCompositeGetAccess"
152 /*@C
153     DMCompositeGetAccess - Allows one to access the individual packed vectors in their global
154        representation.
155 
156     Collective on DMComposite
157 
158     Input Parameters:
159 +    dm - the packer object
160 -    gvec - the global vector
161 
162     Output Parameters:
163 .    Vec* ... - the packed parallel vectors, NULL for those that are not needed
164 
165     Notes: Use DMCompositeRestoreAccess() to return the vectors when you no longer need them
166 
167     Fortran Notes:
168 
169     Fortran callers must use numbered versions of this routine, e.g., DMCompositeGetAccess4(dm,gvec,vec1,vec2,vec3,vec4)
170     or use the alternative interface DMCompositeGetAccessArray().
171 
172     Level: advanced
173 
174 .seealso: DMCompositeGetEntries(), DMCompositeScatter()
175 @*/
176 PetscErrorCode  DMCompositeGetAccess(DM dm,Vec gvec,...)
177 {
178   va_list                Argp;
179   PetscErrorCode         ierr;
180   struct DMCompositeLink *next;
181   DM_Composite           *com = (DM_Composite*)dm->data;
182 
183   PetscFunctionBegin;
184   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
185   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
186   next = com->next;
187   if (!com->setup) {
188     ierr = DMSetUp(dm);CHKERRQ(ierr);
189   }
190 
191   /* loop over packed objects, handling one at at time */
192   va_start(Argp,gvec);
193   while (next) {
194     Vec *vec;
195     vec = va_arg(Argp, Vec*);
196     if (vec) {
197       PetscScalar *array;
198       ierr = DMGetGlobalVector(next->dm,vec);CHKERRQ(ierr);
199       ierr = VecGetArray(gvec,&array);CHKERRQ(ierr);
200       ierr = VecPlaceArray(*vec,array+next->rstart);CHKERRQ(ierr);
201       ierr = VecRestoreArray(gvec,&array);CHKERRQ(ierr);
202     }
203     next = next->next;
204   }
205   va_end(Argp);
206   PetscFunctionReturn(0);
207 }
208 
209 #undef __FUNCT__
210 #define __FUNCT__ "DMCompositeGetAccessArray"
211 /*@C
212     DMCompositeGetAccessArray - Allows one to access the individual packed vectors in their global
213        representation.
214 
215     Collective on DMComposite
216 
217     Input Parameters:
218 +    dm - the packer object
219 .    pvec - packed vector
220 .    nwanted - number of vectors wanted
221 -    wanted - sorted array of vectors wanted, or NULL to get all vectors
222 
223     Output Parameters:
224 .    vecs - array of requested global vectors (must be allocated)
225 
226     Notes: Use DMCompositeRestoreAccessArray() to return the vectors when you no longer need them
227 
228     Level: advanced
229 
230 .seealso: DMCompositeGetAccess(), DMCompositeGetEntries(), DMCompositeScatter(), DMCompositeGather()
231 @*/
232 PetscErrorCode  DMCompositeGetAccessArray(DM dm,Vec pvec,PetscInt nwanted,const PetscInt *wanted,Vec *vecs)
233 {
234   PetscErrorCode         ierr;
235   struct DMCompositeLink *link;
236   PetscInt               i,wnum;
237   DM_Composite           *com = (DM_Composite*)dm->data;
238 
239   PetscFunctionBegin;
240   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
241   PetscValidHeaderSpecific(pvec,VEC_CLASSID,2);
242   if (!com->setup) {
243     ierr = DMSetUp(dm);CHKERRQ(ierr);
244   }
245 
246   for (i=0,wnum=0,link=com->next; link && wnum<nwanted; i++,link=link->next) {
247     if (!wanted || i == wanted[wnum]) {
248       PetscScalar *array;
249       Vec v;
250       ierr = DMGetGlobalVector(link->dm,&v);CHKERRQ(ierr);
251       ierr = VecGetArray(pvec,&array);CHKERRQ(ierr);
252       ierr = VecPlaceArray(v,array+link->rstart);CHKERRQ(ierr);
253       ierr = VecRestoreArray(pvec,&array);CHKERRQ(ierr);
254       vecs[wnum++] = v;
255     }
256   }
257   PetscFunctionReturn(0);
258 }
259 
260 #undef __FUNCT__
261 #define __FUNCT__ "DMCompositeRestoreAccess"
262 /*@C
263     DMCompositeRestoreAccess - Returns the vectors obtained with DMCompositeGetAccess()
264        representation.
265 
266     Collective on DMComposite
267 
268     Input Parameters:
269 +    dm - the packer object
270 .    gvec - the global vector
271 -    Vec* ... - the individual parallel vectors, NULL for those that are not needed
272 
273     Level: advanced
274 
275 .seealso  DMCompositeAddDM(), DMCreateGlobalVector(),
276          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeScatter(),
277          DMCompositeRestoreAccess(), DMCompositeGetAccess()
278 
279 @*/
280 PetscErrorCode  DMCompositeRestoreAccess(DM dm,Vec gvec,...)
281 {
282   va_list                Argp;
283   PetscErrorCode         ierr;
284   struct DMCompositeLink *next;
285   DM_Composite           *com = (DM_Composite*)dm->data;
286 
287   PetscFunctionBegin;
288   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
289   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
290   next = com->next;
291   if (!com->setup) {
292     ierr = DMSetUp(dm);CHKERRQ(ierr);
293   }
294 
295   /* loop over packed objects, handling one at at time */
296   va_start(Argp,gvec);
297   while (next) {
298     Vec *vec;
299     vec = va_arg(Argp, Vec*);
300     if (vec) {
301       ierr = VecResetArray(*vec);CHKERRQ(ierr);
302       ierr = DMRestoreGlobalVector(next->dm,vec);CHKERRQ(ierr);
303     }
304     next = next->next;
305   }
306   va_end(Argp);
307   PetscFunctionReturn(0);
308 }
309 
310 #undef __FUNCT__
311 #define __FUNCT__ "DMCompositeRestoreAccessArray"
312 /*@C
313     DMCompositeRestoreAccessArray - Returns the vectors obtained with DMCompositeGetAccessArray()
314 
315     Collective on DMComposite
316 
317     Input Parameters:
318 +    dm - the packer object
319 .    pvec - packed vector
320 .    nwanted - number of vectors wanted
321 .    wanted - sorted array of vectors wanted, or NULL to get all vectors
322 -    vecs - array of global vectors to return
323 
324     Level: advanced
325 
326 .seealso: DMCompositeRestoreAccess(), DMCompositeRestoreEntries(), DMCompositeScatter(), DMCompositeGather()
327 @*/
328 PetscErrorCode  DMCompositeRestoreAccessArray(DM dm,Vec pvec,PetscInt nwanted,const PetscInt *wanted,Vec *vecs)
329 {
330   PetscErrorCode         ierr;
331   struct DMCompositeLink *link;
332   PetscInt               i,wnum;
333   DM_Composite           *com = (DM_Composite*)dm->data;
334 
335   PetscFunctionBegin;
336   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
337   PetscValidHeaderSpecific(pvec,VEC_CLASSID,2);
338   if (!com->setup) {
339     ierr = DMSetUp(dm);CHKERRQ(ierr);
340   }
341 
342   for (i=0,wnum=0,link=com->next; link && wnum<nwanted; i++,link=link->next) {
343     if (!wanted || i == wanted[wnum]) {
344       ierr = VecResetArray(vecs[wnum]);CHKERRQ(ierr);
345       ierr = DMRestoreGlobalVector(link->dm,&vecs[wnum]);CHKERRQ(ierr);
346       wnum++;
347     }
348   }
349   PetscFunctionReturn(0);
350 }
351 
352 #undef __FUNCT__
353 #define __FUNCT__ "DMCompositeScatter"
354 /*@C
355     DMCompositeScatter - Scatters from a global packed vector into its individual local vectors
356 
357     Collective on DMComposite
358 
359     Input Parameters:
360 +    dm - the packer object
361 .    gvec - the global vector
362 -    Vec ... - the individual sequential vectors, NULL for those that are not needed
363 
364     Level: advanced
365 
366 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
367          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
368          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
369 
370 @*/
371 PetscErrorCode  DMCompositeScatter(DM dm,Vec gvec,...)
372 {
373   va_list                Argp;
374   PetscErrorCode         ierr;
375   struct DMCompositeLink *next;
376   PetscInt               cnt;
377   DM_Composite           *com = (DM_Composite*)dm->data;
378 
379   PetscFunctionBegin;
380   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
381   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
382   if (!com->setup) {
383     ierr = DMSetUp(dm);CHKERRQ(ierr);
384   }
385 
386   /* loop over packed objects, handling one at at time */
387   va_start(Argp,gvec);
388   for (cnt=3,next=com->next; next; cnt++,next=next->next) {
389     Vec local;
390     local = va_arg(Argp, Vec);
391     if (local) {
392       Vec         global;
393       PetscScalar *array;
394       PetscValidHeaderSpecific(local,VEC_CLASSID,cnt);
395       ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
396       ierr = VecGetArray(gvec,&array);CHKERRQ(ierr);
397       ierr = VecPlaceArray(global,array+next->rstart);CHKERRQ(ierr);
398       ierr = DMGlobalToLocalBegin(next->dm,global,INSERT_VALUES,local);CHKERRQ(ierr);
399       ierr = DMGlobalToLocalEnd(next->dm,global,INSERT_VALUES,local);CHKERRQ(ierr);
400       ierr = VecRestoreArray(gvec,&array);CHKERRQ(ierr);
401       ierr = VecResetArray(global);CHKERRQ(ierr);
402       ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
403     }
404   }
405   va_end(Argp);
406   PetscFunctionReturn(0);
407 }
408 
409 #undef __FUNCT__
410 #define __FUNCT__ "DMCompositeGather"
411 /*@C
412     DMCompositeGather - Gathers into a global packed vector from its individual local vectors
413 
414     Collective on DMComposite
415 
416     Input Parameter:
417 +    dm - the packer object
418 .    gvec - the global vector
419 -    Vec ... - the individual sequential vectors, NULL for any that are not needed
420 
421     Level: advanced
422 
423 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
424          DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
425          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
426 
427 @*/
428 PetscErrorCode  DMCompositeGather(DM dm,Vec gvec,InsertMode imode,...)
429 {
430   va_list                Argp;
431   PetscErrorCode         ierr;
432   struct DMCompositeLink *next;
433   DM_Composite           *com = (DM_Composite*)dm->data;
434   PetscInt               cnt;
435 
436   PetscFunctionBegin;
437   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
438   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
439   if (!com->setup) {
440     ierr = DMSetUp(dm);CHKERRQ(ierr);
441   }
442 
443   /* loop over packed objects, handling one at at time */
444   va_start(Argp,imode);
445   for (cnt=3,next=com->next; next; cnt++,next=next->next) {
446     Vec local;
447     local = va_arg(Argp, Vec);
448     if (local) {
449       PetscScalar *array;
450       Vec         global;
451       PetscValidHeaderSpecific(local,VEC_CLASSID,cnt);
452       ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
453       ierr = VecGetArray(gvec,&array);CHKERRQ(ierr);
454       ierr = VecPlaceArray(global,array+next->rstart);CHKERRQ(ierr);
455       ierr = DMLocalToGlobalBegin(next->dm,local,imode,global);CHKERRQ(ierr);
456       ierr = DMLocalToGlobalEnd(next->dm,local,imode,global);CHKERRQ(ierr);
457       ierr = VecRestoreArray(gvec,&array);CHKERRQ(ierr);
458       ierr = VecResetArray(global);CHKERRQ(ierr);
459       ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
460     }
461   }
462   va_end(Argp);
463   PetscFunctionReturn(0);
464 }
465 
466 #undef __FUNCT__
467 #define __FUNCT__ "DMCompositeAddDM"
468 /*@C
469     DMCompositeAddDM - adds a DM  vector to a DMComposite
470 
471     Collective on DMComposite
472 
473     Input Parameter:
474 +    dm - the packer object
475 -    dm - the DM object, if the DM is a da you will need to caste it with a (DM)
476 
477     Level: advanced
478 
479 .seealso DMDestroy(), DMCompositeGather(), DMCompositeAddDM(), DMCreateGlobalVector(),
480          DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
481          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
482 
483 @*/
484 PetscErrorCode  DMCompositeAddDM(DM dmc,DM dm)
485 {
486   PetscErrorCode         ierr;
487   PetscInt               n,nlocal;
488   struct DMCompositeLink *mine,*next;
489   Vec                    global,local;
490   DM_Composite           *com = (DM_Composite*)dmc->data;
491 
492   PetscFunctionBegin;
493   PetscValidHeaderSpecific(dmc,DM_CLASSID,1);
494   PetscValidHeaderSpecific(dm,DM_CLASSID,2);
495   next = com->next;
496   if (com->setup) SETERRQ(PetscObjectComm((PetscObject)dmc),PETSC_ERR_ARG_WRONGSTATE,"Cannot add a DM once you have used the DMComposite");
497 
498   /* create new link */
499   ierr = PetscNew(struct DMCompositeLink,&mine);CHKERRQ(ierr);
500   ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
501   ierr = DMGetGlobalVector(dm,&global);CHKERRQ(ierr);
502   ierr = VecGetLocalSize(global,&n);CHKERRQ(ierr);
503   ierr = DMRestoreGlobalVector(dm,&global);CHKERRQ(ierr);
504   ierr = DMGetLocalVector(dm,&local);CHKERRQ(ierr);
505   ierr = VecGetSize(local,&nlocal);CHKERRQ(ierr);
506   ierr = DMRestoreLocalVector(dm,&local);CHKERRQ(ierr);
507 
508   mine->n      = n;
509   mine->nlocal = nlocal;
510   mine->dm     = dm;
511   mine->next   = NULL;
512   com->n      += n;
513 
514   /* add to end of list */
515   if (!next) com->next = mine;
516   else {
517     while (next->next) next = next->next;
518     next->next = mine;
519   }
520   com->nDM++;
521   com->nmine++;
522   PetscFunctionReturn(0);
523 }
524 
525 extern PetscErrorCode  VecView_MPI(Vec,PetscViewer);
526 EXTERN_C_BEGIN
527 #undef __FUNCT__
528 #define __FUNCT__ "VecView_DMComposite"
529 PetscErrorCode  VecView_DMComposite(Vec gvec,PetscViewer viewer)
530 {
531   DM                     dm;
532   PetscErrorCode         ierr;
533   struct DMCompositeLink *next;
534   PetscBool              isdraw;
535   DM_Composite           *com;
536 
537   PetscFunctionBegin;
538   ierr = VecGetDM(gvec, &dm);CHKERRQ(ierr);
539   if (!dm) SETERRQ(PetscObjectComm((PetscObject)gvec),PETSC_ERR_ARG_WRONG,"Vector not generated from a DMComposite");
540   com  = (DM_Composite*)dm->data;
541   next = com->next;
542 
543   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
544   if (!isdraw) {
545     /* do I really want to call this? */
546     ierr = VecView_MPI(gvec,viewer);CHKERRQ(ierr);
547   } else {
548     PetscInt cnt = 0;
549 
550     /* loop over packed objects, handling one at at time */
551     while (next) {
552       Vec         vec;
553       PetscScalar *array;
554       PetscInt    bs;
555 
556       /* Should use VecGetSubVector() eventually, but would need to forward the DM for that to work */
557       ierr = DMGetGlobalVector(next->dm,&vec);CHKERRQ(ierr);
558       ierr = VecGetArray(gvec,&array);CHKERRQ(ierr);
559       ierr = VecPlaceArray(vec,array+next->rstart);CHKERRQ(ierr);
560       ierr = VecRestoreArray(gvec,&array);CHKERRQ(ierr);
561       ierr = VecView(vec,viewer);CHKERRQ(ierr);
562       ierr = VecGetBlockSize(vec,&bs);CHKERRQ(ierr);
563       ierr = VecResetArray(vec);CHKERRQ(ierr);
564       ierr = DMRestoreGlobalVector(next->dm,&vec);CHKERRQ(ierr);
565       ierr = PetscViewerDrawBaseAdd(viewer,bs);CHKERRQ(ierr);
566       cnt += bs;
567       next = next->next;
568     }
569     ierr = PetscViewerDrawBaseAdd(viewer,-cnt);CHKERRQ(ierr);
570   }
571   PetscFunctionReturn(0);
572 }
573 EXTERN_C_END
574 
575 
576 #undef __FUNCT__
577 #define __FUNCT__ "DMCreateGlobalVector_Composite"
578 PetscErrorCode  DMCreateGlobalVector_Composite(DM dm,Vec *gvec)
579 {
580   PetscErrorCode ierr;
581   DM_Composite   *com = (DM_Composite*)dm->data;
582 
583   PetscFunctionBegin;
584   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
585   ierr = DMSetUp(dm);CHKERRQ(ierr);
586   ierr = VecCreateMPI(PetscObjectComm((PetscObject)dm),com->n,com->N,gvec);CHKERRQ(ierr);
587   ierr = VecSetDM(*gvec, dm);CHKERRQ(ierr);
588   ierr = VecSetOperation(*gvec,VECOP_VIEW,(void (*)(void))VecView_DMComposite);CHKERRQ(ierr);
589   PetscFunctionReturn(0);
590 }
591 
592 #undef __FUNCT__
593 #define __FUNCT__ "DMCreateLocalVector_Composite"
594 PetscErrorCode  DMCreateLocalVector_Composite(DM dm,Vec *lvec)
595 {
596   PetscErrorCode ierr;
597   DM_Composite   *com = (DM_Composite*)dm->data;
598 
599   PetscFunctionBegin;
600   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
601   if (!com->setup) {
602     ierr = DMSetUp(dm);CHKERRQ(ierr);
603   }
604   ierr = VecCreateSeq(PetscObjectComm((PetscObject)dm),com->nghost,lvec);CHKERRQ(ierr);
605   ierr = VecSetDM(*lvec, dm);CHKERRQ(ierr);
606   PetscFunctionReturn(0);
607 }
608 
609 #undef __FUNCT__
610 #define __FUNCT__ "DMCompositeGetISLocalToGlobalMappings"
611 /*@C
612     DMCompositeGetISLocalToGlobalMappings - gets an ISLocalToGlobalMapping for each DM in the DMComposite, maps to the composite global space
613 
614     Collective on DM
615 
616     Input Parameter:
617 .    dm - the packer object
618 
619     Output Parameters:
620 .    ltogs - the individual mappings for each packed vector. Note that this includes
621            all the ghost points that individual ghosted DMDA's may have.
622 
623     Level: advanced
624 
625     Notes:
626        Each entry of ltogs should be destroyed with ISLocalToGlobalMappingDestroy(), the ltogs array should be freed with PetscFree().
627 
628 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
629          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetAccess(), DMCompositeScatter(),
630          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(),DMCompositeGetEntries()
631 
632 @*/
633 PetscErrorCode  DMCompositeGetISLocalToGlobalMappings(DM dm,ISLocalToGlobalMapping **ltogs)
634 {
635   PetscErrorCode         ierr;
636   PetscInt               i,*idx,n,cnt;
637   struct DMCompositeLink *next;
638   PetscMPIInt            rank;
639   DM_Composite           *com = (DM_Composite*)dm->data;
640 
641   PetscFunctionBegin;
642   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
643   ierr = DMSetUp(dm);CHKERRQ(ierr);
644   ierr = PetscMalloc((com->nDM)*sizeof(ISLocalToGlobalMapping),ltogs);CHKERRQ(ierr);
645   next = com->next;
646   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
647 
648   /* loop over packed objects, handling one at at time */
649   cnt = 0;
650   while (next) {
651     ISLocalToGlobalMapping ltog;
652     PetscMPIInt            size;
653     const PetscInt         *suboff,*indices;
654     Vec                    global;
655 
656     /* Get sub-DM global indices for each local dof */
657     ierr = DMGetLocalToGlobalMapping(next->dm,&ltog);CHKERRQ(ierr);
658     ierr = ISLocalToGlobalMappingGetSize(ltog,&n);CHKERRQ(ierr);
659     ierr = ISLocalToGlobalMappingGetIndices(ltog,&indices);CHKERRQ(ierr);
660     ierr = PetscMalloc(n*sizeof(PetscInt),&idx);CHKERRQ(ierr);
661 
662     /* Get the offsets for the sub-DM global vector */
663     ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
664     ierr = VecGetOwnershipRanges(global,&suboff);CHKERRQ(ierr);
665     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)global),&size);CHKERRQ(ierr);
666 
667     /* Shift the sub-DM definition of the global space to the composite global space */
668     for (i=0; i<n; i++) {
669       PetscInt subi = indices[i],lo = 0,hi = size,t;
670       /* Binary search to find which rank owns subi */
671       while (hi-lo > 1) {
672         t = lo + (hi-lo)/2;
673         if (suboff[t] > subi) hi = t;
674         else                  lo = t;
675       }
676       idx[i] = subi - suboff[lo] + next->grstarts[lo];
677     }
678     ierr = ISLocalToGlobalMappingRestoreIndices(ltog,&indices);CHKERRQ(ierr);
679     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm),n,idx,PETSC_OWN_POINTER,&(*ltogs)[cnt]);CHKERRQ(ierr);
680     ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
681     next = next->next;
682     cnt++;
683   }
684   PetscFunctionReturn(0);
685 }
686 
687 #undef __FUNCT__
688 #define __FUNCT__ "DMCompositeGetLocalISs"
689 /*@C
690    DMCompositeGetLocalISs - Gets index sets for each component of a composite local vector
691 
692    Not Collective
693 
694    Input Arguments:
695 . dm - composite DM
696 
697    Output Arguments:
698 . is - array of serial index sets for each each component of the DMComposite
699 
700    Level: intermediate
701 
702    Notes:
703    At present, a composite local vector does not normally exist.  This function is used to provide index sets for
704    MatGetLocalSubMatrix().  In the future, the scatters for each entry in the DMComposite may be be merged into a single
705    scatter to a composite local vector.  The user should not typically need to know which is being done.
706 
707    To get the composite global indices at all local points (including ghosts), use DMCompositeGetISLocalToGlobalMappings().
708 
709    To get index sets for pieces of the composite global vector, use DMCompositeGetGlobalISs().
710 
711    Each returned IS should be destroyed with ISDestroy(), the array should be freed with PetscFree().
712 
713 .seealso: DMCompositeGetGlobalISs(), DMCompositeGetISLocalToGlobalMappings(), MatGetLocalSubMatrix(), MatCreateLocalRef()
714 @*/
715 PetscErrorCode  DMCompositeGetLocalISs(DM dm,IS **is)
716 {
717   PetscErrorCode         ierr;
718   DM_Composite           *com = (DM_Composite*)dm->data;
719   struct DMCompositeLink *link;
720   PetscInt               cnt,start;
721 
722   PetscFunctionBegin;
723   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
724   PetscValidPointer(is,2);
725   ierr = PetscMalloc(com->nmine*sizeof(IS),is);CHKERRQ(ierr);
726   for (cnt=0,start=0,link=com->next; link; start+=link->nlocal,cnt++,link=link->next) {
727     PetscInt bs;
728     ierr = ISCreateStride(PETSC_COMM_SELF,link->nlocal,start,1,&(*is)[cnt]);CHKERRQ(ierr);
729     ierr = DMGetBlockSize(link->dm,&bs);CHKERRQ(ierr);
730     ierr = ISSetBlockSize((*is)[cnt],bs);CHKERRQ(ierr);
731   }
732   PetscFunctionReturn(0);
733 }
734 
735 #undef __FUNCT__
736 #define __FUNCT__ "DMCompositeGetGlobalISs"
737 /*@C
738     DMCompositeGetGlobalISs - Gets the index sets for each composed object
739 
740     Collective on DMComposite
741 
742     Input Parameter:
743 .    dm - the packer object
744 
745     Output Parameters:
746 .    is - the array of index sets
747 
748     Level: advanced
749 
750     Notes:
751        The is entries should be destroyed with ISDestroy(), the is array should be freed with PetscFree()
752 
753        These could be used to extract a subset of vector entries for a "multi-physics" preconditioner
754 
755        Use DMCompositeGetLocalISs() for index sets in the packed local numbering, and
756        DMCompositeGetISLocalToGlobalMappings() for to map local sub-DM (including ghost) indices to packed global
757        indices.
758 
759 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
760          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetAccess(), DMCompositeScatter(),
761          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(),DMCompositeGetEntries()
762 
763 @*/
764 
765 PetscErrorCode  DMCompositeGetGlobalISs(DM dm,IS *is[])
766 {
767   PetscErrorCode         ierr;
768   PetscInt               cnt = 0,*idx,i;
769   struct DMCompositeLink *next;
770   PetscMPIInt            rank;
771   DM_Composite           *com = (DM_Composite*)dm->data;
772 
773   PetscFunctionBegin;
774   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
775   ierr = PetscMalloc((com->nDM)*sizeof(IS),is);CHKERRQ(ierr);
776   next = com->next;
777   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
778 
779   /* loop over packed objects, handling one at at time */
780   while (next) {
781     ierr = PetscMalloc(next->n*sizeof(PetscInt),&idx);CHKERRQ(ierr);
782     for (i=0; i<next->n; i++) idx[i] = next->grstart + i;
783     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm),next->n,idx,PETSC_OWN_POINTER,&(*is)[cnt]);CHKERRQ(ierr);
784     cnt++;
785     next = next->next;
786   }
787   PetscFunctionReturn(0);
788 }
789 
790 #undef __FUNCT__
791 #define __FUNCT__ "DMCreateFieldIS_Composite"
792 PetscErrorCode DMCreateFieldIS_Composite(DM dm, PetscInt *numFields,char ***fieldNames, IS **fields)
793 {
794   PetscInt       nDM;
795   DM             *dms;
796   PetscInt       i;
797   PetscErrorCode ierr;
798 
799   PetscFunctionBegin;
800   ierr = DMCompositeGetNumberDM(dm, &nDM);CHKERRQ(ierr);
801   if (numFields) *numFields = nDM;
802   ierr = DMCompositeGetGlobalISs(dm, fields);CHKERRQ(ierr);
803   if (fieldNames) {
804     ierr = PetscMalloc(nDM*sizeof(DM), &dms);CHKERRQ(ierr);
805     ierr = PetscMalloc(nDM*sizeof(const char*), fieldNames);CHKERRQ(ierr);
806     ierr = DMCompositeGetEntriesArray(dm, dms);CHKERRQ(ierr);
807     for (i=0; i<nDM; i++) {
808       char       buf[256];
809       const char *splitname;
810 
811       /* Split naming precedence: object name, prefix, number */
812       splitname = ((PetscObject) dm)->name;
813       if (!splitname) {
814         ierr = PetscObjectGetOptionsPrefix((PetscObject)dms[i],&splitname);CHKERRQ(ierr);
815         if (splitname) {
816           size_t len;
817           ierr                 = PetscStrncpy(buf,splitname,sizeof(buf));CHKERRQ(ierr);
818           buf[sizeof(buf) - 1] = 0;
819           ierr                 = PetscStrlen(buf,&len);CHKERRQ(ierr);
820           if (buf[len-1] == '_') buf[len-1] = 0; /* Remove trailing underscore if it was used */
821           splitname = buf;
822         }
823       }
824       if (!splitname) {
825         ierr      = PetscSNPrintf(buf,sizeof(buf),"%D",i);CHKERRQ(ierr);
826         splitname = buf;
827       }
828       ierr = PetscStrallocpy(splitname,&(*fieldNames)[i]);CHKERRQ(ierr);
829     }
830     ierr = PetscFree(dms);CHKERRQ(ierr);
831   }
832   PetscFunctionReturn(0);
833 }
834 
835 /*
836  This could take over from DMCreateFieldIS(), as it is more general,
837  making DMCreateFieldIS() a special case -- calling with dmlist == NULL;
838  At this point it's probably best to be less intrusive, however.
839  */
840 #undef __FUNCT__
841 #define __FUNCT__ "DMCreateFieldDecomposition_Composite"
842 PetscErrorCode DMCreateFieldDecomposition_Composite(DM dm, PetscInt *len,char ***namelist, IS **islist, DM **dmlist)
843 {
844   PetscInt       nDM;
845   PetscInt       i;
846   PetscErrorCode ierr;
847 
848   PetscFunctionBegin;
849   ierr = DMCreateFieldIS_Composite(dm, len, namelist, islist);CHKERRQ(ierr);
850   if (dmlist) {
851     ierr = DMCompositeGetNumberDM(dm, &nDM);CHKERRQ(ierr);
852     ierr = PetscMalloc(nDM*sizeof(DM), dmlist);CHKERRQ(ierr);
853     ierr = DMCompositeGetEntriesArray(dm, *dmlist);CHKERRQ(ierr);
854     for (i=0; i<nDM; i++) {
855       ierr = PetscObjectReference((PetscObject)((*dmlist)[i]));CHKERRQ(ierr);
856     }
857   }
858   PetscFunctionReturn(0);
859 }
860 
861 
862 
863 /* -------------------------------------------------------------------------------------*/
864 #undef __FUNCT__
865 #define __FUNCT__ "DMCompositeGetLocalVectors"
866 /*@C
867     DMCompositeGetLocalVectors - Gets local vectors for each part of a DMComposite.
868        Use DMCompositeRestoreLocalVectors() to return them.
869 
870     Not Collective
871 
872     Input Parameter:
873 .    dm - the packer object
874 
875     Output Parameter:
876 .   Vec ... - the individual sequential Vecs
877 
878     Level: advanced
879 
880 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
881          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
882          DMCompositeRestoreLocalVectors(), DMCompositeScatter(), DMCompositeGetEntries()
883 
884 @*/
885 PetscErrorCode  DMCompositeGetLocalVectors(DM dm,...)
886 {
887   va_list                Argp;
888   PetscErrorCode         ierr;
889   struct DMCompositeLink *next;
890   DM_Composite           *com = (DM_Composite*)dm->data;
891 
892   PetscFunctionBegin;
893   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
894   next = com->next;
895   /* loop over packed objects, handling one at at time */
896   va_start(Argp,dm);
897   while (next) {
898     Vec *vec;
899     vec = va_arg(Argp, Vec*);
900     if (vec) {ierr = DMGetLocalVector(next->dm,vec);CHKERRQ(ierr);}
901     next = next->next;
902   }
903   va_end(Argp);
904   PetscFunctionReturn(0);
905 }
906 
907 #undef __FUNCT__
908 #define __FUNCT__ "DMCompositeRestoreLocalVectors"
909 /*@C
910     DMCompositeRestoreLocalVectors - Restores local vectors for each part of a DMComposite.
911 
912     Not Collective
913 
914     Input Parameter:
915 .    dm - the packer object
916 
917     Output Parameter:
918 .   Vec ... - the individual sequential Vecs
919 
920     Level: advanced
921 
922 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
923          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
924          DMCompositeGetLocalVectors(), DMCompositeScatter(), DMCompositeGetEntries()
925 
926 @*/
927 PetscErrorCode  DMCompositeRestoreLocalVectors(DM dm,...)
928 {
929   va_list                Argp;
930   PetscErrorCode         ierr;
931   struct DMCompositeLink *next;
932   DM_Composite           *com = (DM_Composite*)dm->data;
933 
934   PetscFunctionBegin;
935   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
936   next = com->next;
937   /* loop over packed objects, handling one at at time */
938   va_start(Argp,dm);
939   while (next) {
940     Vec *vec;
941     vec = va_arg(Argp, Vec*);
942     if (vec) {ierr = DMRestoreLocalVector(next->dm,vec);CHKERRQ(ierr);}
943     next = next->next;
944   }
945   va_end(Argp);
946   PetscFunctionReturn(0);
947 }
948 
949 /* -------------------------------------------------------------------------------------*/
950 #undef __FUNCT__
951 #define __FUNCT__ "DMCompositeGetEntries"
952 /*@C
953     DMCompositeGetEntries - Gets the DM for each entry in a DMComposite.
954 
955     Not Collective
956 
957     Input Parameter:
958 .    dm - the packer object
959 
960     Output Parameter:
961 .   DM ... - the individual entries (DMs)
962 
963     Level: advanced
964 
965 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(), DMCompositeGetEntriesArray()
966          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
967          DMCompositeRestoreLocalVectors(), DMCompositeGetLocalVectors(),  DMCompositeScatter(),
968          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors()
969 
970 @*/
971 PetscErrorCode  DMCompositeGetEntries(DM dm,...)
972 {
973   va_list                Argp;
974   struct DMCompositeLink *next;
975   DM_Composite           *com = (DM_Composite*)dm->data;
976 
977   PetscFunctionBegin;
978   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
979   next = com->next;
980   /* loop over packed objects, handling one at at time */
981   va_start(Argp,dm);
982   while (next) {
983     DM *dmn;
984     dmn = va_arg(Argp, DM*);
985     if (dmn) *dmn = next->dm;
986     next = next->next;
987   }
988   va_end(Argp);
989   PetscFunctionReturn(0);
990 }
991 
992 #undef __FUNCT__
993 #define __FUNCT__ "DMCompositeGetEntriesArray"
994 /*@C
995     DMCompositeGetEntriesArray - Gets the DM for each entry in a DMComposite.
996 
997     Not Collective
998 
999     Input Parameter:
1000 +    dm - the packer object
1001 -    dms - array of sufficient length (see DMCompositeGetNumberDM()), holds the DMs on output
1002 
1003     Level: advanced
1004 
1005 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(), DMCompositeGetEntries()
1006          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
1007          DMCompositeRestoreLocalVectors(), DMCompositeGetLocalVectors(),  DMCompositeScatter(),
1008          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors()
1009 
1010 @*/
1011 PetscErrorCode DMCompositeGetEntriesArray(DM dm,DM dms[])
1012 {
1013   struct DMCompositeLink *next;
1014   DM_Composite           *com = (DM_Composite*)dm->data;
1015   PetscInt               i;
1016 
1017   PetscFunctionBegin;
1018   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1019   /* loop over packed objects, handling one at at time */
1020   for (next=com->next,i=0; next; next=next->next,i++) dms[i] = next->dm;
1021   PetscFunctionReturn(0);
1022 }
1023 
1024 #undef __FUNCT__
1025 #define __FUNCT__ "DMRefine_Composite"
1026 PetscErrorCode  DMRefine_Composite(DM dmi,MPI_Comm comm,DM *fine)
1027 {
1028   PetscErrorCode         ierr;
1029   struct DMCompositeLink *next;
1030   DM_Composite           *com = (DM_Composite*)dmi->data;
1031   DM                     dm;
1032 
1033   PetscFunctionBegin;
1034   PetscValidHeaderSpecific(dmi,DM_CLASSID,1);
1035   if (comm == MPI_COMM_NULL) {
1036     ierr = PetscObjectGetComm((PetscObject)dmi,&comm);CHKERRQ(ierr);
1037   }
1038   ierr = DMSetUp(dmi);CHKERRQ(ierr);
1039   next = com->next;
1040   ierr = DMCompositeCreate(comm,fine);CHKERRQ(ierr);
1041 
1042   /* loop over packed objects, handling one at at time */
1043   while (next) {
1044     ierr = DMRefine(next->dm,comm,&dm);CHKERRQ(ierr);
1045     ierr = DMCompositeAddDM(*fine,dm);CHKERRQ(ierr);
1046     ierr = PetscObjectDereference((PetscObject)dm);CHKERRQ(ierr);
1047     next = next->next;
1048   }
1049   PetscFunctionReturn(0);
1050 }
1051 
1052 #undef __FUNCT__
1053 #define __FUNCT__ "DMCoarsen_Composite"
1054 PetscErrorCode  DMCoarsen_Composite(DM dmi,MPI_Comm comm,DM *fine)
1055 {
1056   PetscErrorCode         ierr;
1057   struct DMCompositeLink *next;
1058   DM_Composite           *com = (DM_Composite*)dmi->data;
1059   DM                     dm;
1060 
1061   PetscFunctionBegin;
1062   PetscValidHeaderSpecific(dmi,DM_CLASSID,1);
1063   ierr = DMSetUp(dmi);CHKERRQ(ierr);
1064   if (comm == MPI_COMM_NULL) {
1065     ierr = PetscObjectGetComm((PetscObject)dmi,&comm);CHKERRQ(ierr);
1066   }
1067   next = com->next;
1068   ierr = DMCompositeCreate(comm,fine);CHKERRQ(ierr);
1069 
1070   /* loop over packed objects, handling one at at time */
1071   while (next) {
1072     ierr = DMCoarsen(next->dm,comm,&dm);CHKERRQ(ierr);
1073     ierr = DMCompositeAddDM(*fine,dm);CHKERRQ(ierr);
1074     ierr = PetscObjectDereference((PetscObject)dm);CHKERRQ(ierr);
1075     next = next->next;
1076   }
1077   PetscFunctionReturn(0);
1078 }
1079 
1080 #undef __FUNCT__
1081 #define __FUNCT__ "DMCreateInterpolation_Composite"
1082 PetscErrorCode  DMCreateInterpolation_Composite(DM coarse,DM fine,Mat *A,Vec *v)
1083 {
1084   PetscErrorCode         ierr;
1085   PetscInt               m,n,M,N,nDM,i;
1086   struct DMCompositeLink *nextc;
1087   struct DMCompositeLink *nextf;
1088   Vec                    gcoarse,gfine,*vecs;
1089   DM_Composite           *comcoarse = (DM_Composite*)coarse->data;
1090   DM_Composite           *comfine   = (DM_Composite*)fine->data;
1091   Mat                    *mats;
1092 
1093   PetscFunctionBegin;
1094   PetscValidHeaderSpecific(coarse,DM_CLASSID,1);
1095   PetscValidHeaderSpecific(fine,DM_CLASSID,2);
1096   ierr = DMSetUp(coarse);CHKERRQ(ierr);
1097   ierr = DMSetUp(fine);CHKERRQ(ierr);
1098   /* use global vectors only for determining matrix layout */
1099   ierr = DMGetGlobalVector(coarse,&gcoarse);CHKERRQ(ierr);
1100   ierr = DMGetGlobalVector(fine,&gfine);CHKERRQ(ierr);
1101   ierr = VecGetLocalSize(gcoarse,&n);CHKERRQ(ierr);
1102   ierr = VecGetLocalSize(gfine,&m);CHKERRQ(ierr);
1103   ierr = VecGetSize(gcoarse,&N);CHKERRQ(ierr);
1104   ierr = VecGetSize(gfine,&M);CHKERRQ(ierr);
1105   ierr = DMRestoreGlobalVector(coarse,&gcoarse);CHKERRQ(ierr);
1106   ierr = DMRestoreGlobalVector(fine,&gfine);CHKERRQ(ierr);
1107 
1108   nDM = comfine->nDM;
1109   if (nDM != comcoarse->nDM) SETERRQ2(PetscObjectComm((PetscObject)fine),PETSC_ERR_ARG_INCOMP,"Fine DMComposite has %D entries, but coarse has %D",nDM,comcoarse->nDM);
1110   ierr = PetscMalloc(nDM*nDM*sizeof(Mat),&mats);CHKERRQ(ierr);
1111   ierr = PetscMemzero(mats,nDM*nDM*sizeof(Mat));CHKERRQ(ierr);
1112   if (v) {
1113     ierr = PetscMalloc(nDM*sizeof(Vec),&vecs);CHKERRQ(ierr);
1114     ierr = PetscMemzero(vecs,nDM*sizeof(Vec));CHKERRQ(ierr);
1115   }
1116 
1117   /* loop over packed objects, handling one at at time */
1118   for (nextc=comcoarse->next,nextf=comfine->next,i=0; nextc; nextc=nextc->next,nextf=nextf->next,i++) {
1119     if (!v) {
1120       ierr = DMCreateInterpolation(nextc->dm,nextf->dm,&mats[i*nDM+i],NULL);CHKERRQ(ierr);
1121     } else {
1122       ierr = DMCreateInterpolation(nextc->dm,nextf->dm,&mats[i*nDM+i],&vecs[i]);CHKERRQ(ierr);
1123     }
1124   }
1125   ierr = MatCreateNest(PetscObjectComm((PetscObject)fine),nDM,NULL,nDM,NULL,mats,A);CHKERRQ(ierr);
1126   if (v) {
1127     ierr = VecCreateNest(PetscObjectComm((PetscObject)fine),nDM,NULL,vecs,v);CHKERRQ(ierr);
1128   }
1129   for (i=0; i<nDM*nDM; i++) {ierr = MatDestroy(&mats[i]);CHKERRQ(ierr);}
1130   ierr = PetscFree(mats);CHKERRQ(ierr);
1131   if (v) {
1132     for (i=0; i<nDM; i++) {ierr = VecDestroy(&vecs[i]);CHKERRQ(ierr);}
1133     ierr = PetscFree(vecs);CHKERRQ(ierr);
1134   }
1135   PetscFunctionReturn(0);
1136 }
1137 
1138 #undef __FUNCT__
1139 #define __FUNCT__ "DMCreateLocalToGlobalMapping_Composite"
1140 static PetscErrorCode DMCreateLocalToGlobalMapping_Composite(DM dm)
1141 {
1142   DM_Composite           *com = (DM_Composite*)dm->data;
1143   ISLocalToGlobalMapping *ltogs;
1144   PetscInt               i;
1145   PetscErrorCode         ierr;
1146 
1147   PetscFunctionBegin;
1148   /* Set the ISLocalToGlobalMapping on the new matrix */
1149   ierr = DMCompositeGetISLocalToGlobalMappings(dm,&ltogs);CHKERRQ(ierr);
1150   ierr = ISLocalToGlobalMappingConcatenate(PetscObjectComm((PetscObject)dm),com->nDM,ltogs,&dm->ltogmap);CHKERRQ(ierr);
1151   for (i=0; i<com->nDM; i++) {ierr = ISLocalToGlobalMappingDestroy(&ltogs[i]);CHKERRQ(ierr);}
1152   ierr = PetscFree(ltogs);CHKERRQ(ierr);
1153   PetscFunctionReturn(0);
1154 }
1155 
1156 
1157 #undef __FUNCT__
1158 #define __FUNCT__ "DMCreateColoring_Composite"
1159 PetscErrorCode  DMCreateColoring_Composite(DM dm,ISColoringType ctype,MatType mtype,ISColoring *coloring)
1160 {
1161   PetscErrorCode  ierr;
1162   PetscInt        n,i,cnt;
1163   ISColoringValue *colors;
1164   PetscBool       dense  = PETSC_FALSE;
1165   ISColoringValue maxcol = 0;
1166   DM_Composite    *com   = (DM_Composite*)dm->data;
1167 
1168   PetscFunctionBegin;
1169   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1170   if (ctype == IS_COLORING_GHOSTED) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only global coloring supported");
1171   else if (ctype == IS_COLORING_GLOBAL) {
1172     n = com->n;
1173   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Unknown ISColoringType");
1174   ierr = PetscMalloc(n*sizeof(ISColoringValue),&colors);CHKERRQ(ierr); /* freed in ISColoringDestroy() */
1175 
1176   ierr = PetscOptionsGetBool(NULL,"-dmcomposite_dense_jacobian",&dense,NULL);CHKERRQ(ierr);
1177   if (dense) {
1178     for (i=0; i<n; i++) {
1179       colors[i] = (ISColoringValue)(com->rstart + i);
1180     }
1181     maxcol = com->N;
1182   } else {
1183     struct DMCompositeLink *next = com->next;
1184     PetscMPIInt            rank;
1185 
1186     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
1187     cnt  = 0;
1188     while (next) {
1189       ISColoring lcoloring;
1190 
1191       ierr = DMCreateColoring(next->dm,IS_COLORING_GLOBAL,mtype,&lcoloring);CHKERRQ(ierr);
1192       for (i=0; i<lcoloring->N; i++) {
1193         colors[cnt++] = maxcol + lcoloring->colors[i];
1194       }
1195       maxcol += lcoloring->n;
1196       ierr    = ISColoringDestroy(&lcoloring);CHKERRQ(ierr);
1197       next    = next->next;
1198     }
1199   }
1200   ierr = ISColoringCreate(PetscObjectComm((PetscObject)dm),maxcol,n,colors,coloring);CHKERRQ(ierr);
1201   PetscFunctionReturn(0);
1202 }
1203 
1204 #undef __FUNCT__
1205 #define __FUNCT__ "DMGlobalToLocalBegin_Composite"
1206 PetscErrorCode  DMGlobalToLocalBegin_Composite(DM dm,Vec gvec,InsertMode mode,Vec lvec)
1207 {
1208   PetscErrorCode         ierr;
1209   struct DMCompositeLink *next;
1210   PetscInt               cnt = 3;
1211   PetscMPIInt            rank;
1212   PetscScalar            *garray,*larray;
1213   DM_Composite           *com = (DM_Composite*)dm->data;
1214 
1215   PetscFunctionBegin;
1216   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1217   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
1218   next = com->next;
1219   if (!com->setup) {
1220     ierr = DMSetUp(dm);CHKERRQ(ierr);
1221   }
1222   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
1223   ierr = VecGetArray(gvec,&garray);CHKERRQ(ierr);
1224   ierr = VecGetArray(lvec,&larray);CHKERRQ(ierr);
1225 
1226   /* loop over packed objects, handling one at at time */
1227   while (next) {
1228     Vec      local,global;
1229     PetscInt N;
1230 
1231     ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
1232     ierr = VecGetLocalSize(global,&N);CHKERRQ(ierr);
1233     ierr = VecPlaceArray(global,garray);CHKERRQ(ierr);
1234     ierr = DMGetLocalVector(next->dm,&local);CHKERRQ(ierr);
1235     ierr = VecPlaceArray(local,larray);CHKERRQ(ierr);
1236     ierr = DMGlobalToLocalBegin(next->dm,global,mode,local);CHKERRQ(ierr);
1237     ierr = DMGlobalToLocalEnd(next->dm,global,mode,local);CHKERRQ(ierr);
1238     ierr = VecResetArray(global);CHKERRQ(ierr);
1239     ierr = VecResetArray(local);CHKERRQ(ierr);
1240     ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
1241     ierr = DMRestoreGlobalVector(next->dm,&local);CHKERRQ(ierr);
1242     cnt++;
1243     larray += next->nlocal;
1244     next    = next->next;
1245   }
1246 
1247   ierr = VecRestoreArray(gvec,NULL);CHKERRQ(ierr);
1248   ierr = VecRestoreArray(lvec,NULL);CHKERRQ(ierr);
1249   PetscFunctionReturn(0);
1250 }
1251 
1252 #undef __FUNCT__
1253 #define __FUNCT__ "DMGlobalToLocalEnd_Composite"
1254 PetscErrorCode  DMGlobalToLocalEnd_Composite(DM dm,Vec gvec,InsertMode mode,Vec lvec)
1255 {
1256   PetscFunctionBegin;
1257   PetscFunctionReturn(0);
1258 }
1259 
1260 /*MC
1261    DMCOMPOSITE = "composite" - A DM object that is used to manage data for a collection of DMs
1262 
1263 
1264 
1265   Level: intermediate
1266 
1267 .seealso: DMType, DMCOMPOSITE, DMDACreate(), DMCreate(), DMSetType(), DMCompositeCreate()
1268 M*/
1269 
1270 
1271 EXTERN_C_BEGIN
1272 #undef __FUNCT__
1273 #define __FUNCT__ "DMCreate_Composite"
1274 PetscErrorCode  DMCreate_Composite(DM p)
1275 {
1276   PetscErrorCode ierr;
1277   DM_Composite   *com;
1278 
1279   PetscFunctionBegin;
1280   ierr      = PetscNewLog(p,DM_Composite,&com);CHKERRQ(ierr);
1281   p->data   = com;
1282   ierr      = PetscObjectChangeTypeName((PetscObject)p,"DMComposite");CHKERRQ(ierr);
1283   com->n    = 0;
1284   com->next = NULL;
1285   com->nDM  = 0;
1286 
1287   p->ops->createglobalvector              = DMCreateGlobalVector_Composite;
1288   p->ops->createlocalvector               = DMCreateLocalVector_Composite;
1289   p->ops->createlocaltoglobalmapping      = DMCreateLocalToGlobalMapping_Composite;
1290   p->ops->createlocaltoglobalmappingblock = 0;
1291   p->ops->createfieldis                   = DMCreateFieldIS_Composite;
1292   p->ops->createfielddecomposition        = DMCreateFieldDecomposition_Composite;
1293   p->ops->refine                          = DMRefine_Composite;
1294   p->ops->coarsen                         = DMCoarsen_Composite;
1295   p->ops->createinterpolation             = DMCreateInterpolation_Composite;
1296   p->ops->creatematrix                    = DMCreateMatrix_Composite;
1297   p->ops->getcoloring                     = DMCreateColoring_Composite;
1298   p->ops->globaltolocalbegin              = DMGlobalToLocalBegin_Composite;
1299   p->ops->globaltolocalend                = DMGlobalToLocalEnd_Composite;
1300   p->ops->destroy                         = DMDestroy_Composite;
1301   p->ops->view                            = DMView_Composite;
1302   p->ops->setup                           = DMSetUp_Composite;
1303   PetscFunctionReturn(0);
1304 }
1305 EXTERN_C_END
1306 
1307 #undef __FUNCT__
1308 #define __FUNCT__ "DMCompositeCreate"
1309 /*@C
1310     DMCompositeCreate - Creates a vector packer, used to generate "composite"
1311       vectors made up of several subvectors.
1312 
1313     Collective on MPI_Comm
1314 
1315     Input Parameter:
1316 .   comm - the processors that will share the global vector
1317 
1318     Output Parameters:
1319 .   packer - the packer object
1320 
1321     Level: advanced
1322 
1323 .seealso DMDestroy(), DMCompositeAddDM(), DMCompositeScatter(),
1324          DMCompositeGather(), DMCreateGlobalVector(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess()
1325          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
1326 
1327 @*/
1328 PetscErrorCode  DMCompositeCreate(MPI_Comm comm,DM *packer)
1329 {
1330   PetscErrorCode ierr;
1331 
1332   PetscFunctionBegin;
1333   PetscValidPointer(packer,2);
1334   ierr = DMCreate(comm,packer);CHKERRQ(ierr);
1335   ierr = DMSetType(*packer,DMCOMPOSITE);CHKERRQ(ierr);
1336   PetscFunctionReturn(0);
1337 }
1338