xref: /petsc/src/dm/impls/composite/pack.c (revision 193ac0bc5128976c4ec2c1a67f3f9cb026b77f22)
1 
2 #include "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 (DMDA's and arrays) 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     if (prev->type == DMCOMPOSITE_DM) {
46       ierr = DMDestroy(&prev->dm);CHKERRQ(ierr);
47     }
48     ierr = PetscFree(prev->grstarts);CHKERRQ(ierr);
49     ierr = PetscFree(prev);CHKERRQ(ierr);
50   }
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 = PetscTypeCompare((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 and %d redundant arrays\n",com->nDM,com->nredundant);CHKERRQ(ierr);
70     ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr);
71     for (i=0; lnk; lnk=lnk->next,i++) {
72       if (lnk->dm) {
73         ierr = PetscViewerASCIIPrintf(v,"Link %d: DM of type %s\n",i,((PetscObject)lnk->dm)->type_name);CHKERRQ(ierr);
74         ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr);
75         ierr = DMView(lnk->dm,v);CHKERRQ(ierr);
76         ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr);
77       } else {
78         ierr = PetscViewerASCIIPrintf(v,"Link %d: Redundant array of size %d owned by rank %d\n",i,lnk->nlocal,lnk->rank);CHKERRQ(ierr);
79       }
80     }
81     ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr);
82   }
83   PetscFunctionReturn(0);
84 }
85 
86 /* --------------------------------------------------------------------------------------*/
87 #undef __FUNCT__
88 #define __FUNCT__ "DMSetUp_Composite"
89 PetscErrorCode  DMSetUp_Composite(DM dm)
90 {
91   PetscErrorCode         ierr;
92   PetscInt               nprev = 0;
93   PetscMPIInt            rank,size;
94   DM_Composite           *com = (DM_Composite*)dm->data;
95   struct DMCompositeLink *next = com->next;
96   PetscLayout            map;
97 
98   PetscFunctionBegin;
99   if (com->setup) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"Packer has already been setup");
100   ierr = PetscLayoutCreate(((PetscObject)dm)->comm,&map);CHKERRQ(ierr);
101   ierr = PetscLayoutSetLocalSize(map,com->n);CHKERRQ(ierr);
102   ierr = PetscLayoutSetSize(map,PETSC_DETERMINE);CHKERRQ(ierr);
103   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
104   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
105   ierr = PetscLayoutGetSize(map,&com->N);CHKERRQ(ierr);
106   ierr = PetscLayoutGetRange(map,&com->rstart,PETSC_NULL);CHKERRQ(ierr);
107   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
108 
109   /* now set the rstart for each linked array/vector */
110   ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
111   ierr = MPI_Comm_size(((PetscObject)dm)->comm,&size);CHKERRQ(ierr);
112   while (next) {
113     next->rstart = nprev;
114     nprev += next->n;
115     next->grstart = com->rstart + next->rstart;
116     if (next->type == DMCOMPOSITE_ARRAY) {
117       ierr = MPI_Bcast(&next->grstart,1,MPIU_INT,next->rank,((PetscObject)dm)->comm);CHKERRQ(ierr);
118     } else {
119       ierr = PetscMalloc(size*sizeof(PetscInt),&next->grstarts);CHKERRQ(ierr);
120       ierr = MPI_Allgather(&next->grstart,1,MPIU_INT,next->grstarts,1,MPIU_INT,((PetscObject)dm)->comm);CHKERRQ(ierr);
121     }
122     next = next->next;
123   }
124   com->setup = PETSC_TRUE;
125   PetscFunctionReturn(0);
126 }
127 
128 
129 #undef __FUNCT__
130 #define __FUNCT__ "DMCompositeGetAccess_Array"
131 PetscErrorCode DMCompositeGetAccess_Array(DM dm,struct DMCompositeLink *mine,Vec vec,PetscScalar **array)
132 {
133   PetscErrorCode ierr;
134   PetscScalar    *varray;
135   PetscMPIInt    rank;
136 
137   PetscFunctionBegin;
138   ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
139   if (array) {
140     if (rank == mine->rank) {
141       ierr    = VecGetArray(vec,&varray);CHKERRQ(ierr);
142       *array  = varray + mine->rstart;
143       ierr    = VecRestoreArray(vec,&varray);CHKERRQ(ierr);
144     } else {
145       *array = 0;
146     }
147   }
148   PetscFunctionReturn(0);
149 }
150 
151 #undef __FUNCT__
152 #define __FUNCT__ "DMCompositeGetAccess_DM"
153 PetscErrorCode DMCompositeGetAccess_DM(DM dm,struct DMCompositeLink *mine,Vec vec,Vec *global)
154 {
155   PetscErrorCode ierr;
156   PetscScalar    *array;
157 
158   PetscFunctionBegin;
159   if (global) {
160     ierr    = DMGetGlobalVector(mine->dm,global);CHKERRQ(ierr);
161     ierr    = VecGetArray(vec,&array);CHKERRQ(ierr);
162     ierr    = VecPlaceArray(*global,array+mine->rstart);CHKERRQ(ierr);
163     ierr    = VecRestoreArray(vec,&array);CHKERRQ(ierr);
164   }
165   PetscFunctionReturn(0);
166 }
167 
168 #undef __FUNCT__
169 #define __FUNCT__ "DMCompositeRestoreAccess_Array"
170 PetscErrorCode DMCompositeRestoreAccess_Array(DM dm,struct DMCompositeLink *mine,Vec vec,PetscScalar **array)
171 {
172   PetscFunctionBegin;
173   PetscFunctionReturn(0);
174 }
175 
176 #undef __FUNCT__
177 #define __FUNCT__ "DMCompositeRestoreAccess_DM"
178 PetscErrorCode DMCompositeRestoreAccess_DM(DM dm,struct DMCompositeLink *mine,Vec vec,Vec *global)
179 {
180   PetscErrorCode ierr;
181 
182   PetscFunctionBegin;
183   if (global) {
184     ierr = VecResetArray(*global);CHKERRQ(ierr);
185     ierr = DMRestoreGlobalVector(mine->dm,global);CHKERRQ(ierr);
186   }
187   PetscFunctionReturn(0);
188 }
189 
190 #undef __FUNCT__
191 #define __FUNCT__ "DMCompositeScatter_Array"
192 PetscErrorCode DMCompositeScatter_Array(DM dm,struct DMCompositeLink *mine,Vec vec,PetscScalar *array)
193 {
194   PetscErrorCode ierr;
195   PetscScalar    *varray;
196   PetscMPIInt    rank;
197 
198   PetscFunctionBegin;
199   ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
200   if (rank == mine->rank) {
201     ierr    = VecGetArray(vec,&varray);CHKERRQ(ierr);
202     ierr    = PetscMemcpy(array,varray+mine->rstart,mine->n*sizeof(PetscScalar));CHKERRQ(ierr);
203     ierr    = VecRestoreArray(vec,&varray);CHKERRQ(ierr);
204   }
205   ierr    = MPI_Bcast(array,mine->nlocal,MPIU_SCALAR,mine->rank,((PetscObject)dm)->comm);CHKERRQ(ierr);
206   PetscFunctionReturn(0);
207 }
208 
209 #undef __FUNCT__
210 #define __FUNCT__ "DMCompositeScatter_DM"
211 PetscErrorCode DMCompositeScatter_DM(DM dm,struct DMCompositeLink *mine,Vec vec,Vec local)
212 {
213   PetscErrorCode ierr;
214   PetscScalar    *array;
215   Vec            global;
216 
217   PetscFunctionBegin;
218   ierr = DMGetGlobalVector(mine->dm,&global);CHKERRQ(ierr);
219   ierr = VecGetArray(vec,&array);CHKERRQ(ierr);
220   ierr = VecPlaceArray(global,array+mine->rstart);CHKERRQ(ierr);
221   ierr = DMGlobalToLocalBegin(mine->dm,global,INSERT_VALUES,local);CHKERRQ(ierr);
222   ierr = DMGlobalToLocalEnd(mine->dm,global,INSERT_VALUES,local);CHKERRQ(ierr);
223   ierr = VecRestoreArray(vec,&array);CHKERRQ(ierr);
224   ierr = VecResetArray(global);CHKERRQ(ierr);
225   ierr = DMRestoreGlobalVector(mine->dm,&global);CHKERRQ(ierr);
226   PetscFunctionReturn(0);
227 }
228 
229 #undef __FUNCT__
230 #define __FUNCT__ "DMCompositeGather_Array"
231 PetscErrorCode DMCompositeGather_Array(DM dm,struct DMCompositeLink *mine,Vec vec,InsertMode imode,const PetscScalar *array)
232 {
233   PetscErrorCode ierr;
234   PetscScalar    *varray;
235   PetscMPIInt    rank;
236 
237   PetscFunctionBegin;
238   ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
239   if (rank == mine->rank) {
240     ierr = VecGetArray(vec,&varray);CHKERRQ(ierr);
241     if (varray+mine->rstart == array) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"You need not DMCompositeGather() into objects obtained via DMCompositeGetAccess()");
242   }
243   switch (imode) {
244   case INSERT_VALUES:
245     if (rank == mine->rank) {
246       ierr = PetscMemcpy(varray+mine->rstart,array,mine->n*sizeof(PetscScalar));CHKERRQ(ierr);
247     }
248     break;
249   case ADD_VALUES: {
250     PetscInt          i;
251     void             *source;
252     PetscScalar       *buffer,*dest;
253     if (rank == mine->rank) {
254       dest = &varray[mine->rstart];
255 #if defined(PETSC_HAVE_MPI_IN_PLACE)
256       buffer = dest;
257       source = MPI_IN_PLACE;
258 #else
259       ierr = PetscMalloc(mine->nlocal*sizeof(PetscScalar),&buffer);CHKERRQ(ierr);
260       source = (void *) buffer;
261 #endif
262       for (i=0; i<mine->nlocal; i++) buffer[i] = varray[mine->rstart+i] + array[i];
263     } else {
264       source = (void *) array;
265       dest   = PETSC_NULL;
266     }
267     ierr = MPI_Reduce(source,dest,mine->nlocal,MPIU_SCALAR,MPI_SUM,mine->rank,((PetscObject)dm)->comm);CHKERRQ(ierr);
268 #if !defined(PETSC_HAVE_MPI_IN_PLACE)
269     if (rank == mine->rank) {ierr = PetscFree(source);CHKERRQ(ierr);}
270 #endif
271   } break;
272   default: SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"imode");
273   }
274   if (rank == mine->rank) {ierr = VecRestoreArray(vec,&varray);CHKERRQ(ierr);}
275   PetscFunctionReturn(0);
276 }
277 
278 #undef __FUNCT__
279 #define __FUNCT__ "DMCompositeGather_DM"
280 PetscErrorCode DMCompositeGather_DM(DM dm,struct DMCompositeLink *mine,Vec vec,InsertMode imode,Vec local)
281 {
282   PetscErrorCode ierr;
283   PetscScalar    *array;
284   Vec            global;
285 
286   PetscFunctionBegin;
287   ierr = DMGetGlobalVector(mine->dm,&global);CHKERRQ(ierr);
288   ierr = VecGetArray(vec,&array);CHKERRQ(ierr);
289   ierr = VecPlaceArray(global,array+mine->rstart);CHKERRQ(ierr);
290   ierr = DMLocalToGlobalBegin(mine->dm,local,imode,global);CHKERRQ(ierr);
291   ierr = DMLocalToGlobalEnd(mine->dm,local,imode,global);CHKERRQ(ierr);
292   ierr = VecRestoreArray(vec,&array);CHKERRQ(ierr);
293   ierr = VecResetArray(global);CHKERRQ(ierr);
294   ierr = DMRestoreGlobalVector(mine->dm,&global);CHKERRQ(ierr);
295   PetscFunctionReturn(0);
296 }
297 
298 /* ----------------------------------------------------------------------------------*/
299 
300 #include <stdarg.h>
301 
302 #undef __FUNCT__
303 #define __FUNCT__ "DMCompositeGetNumberDM"
304 /*@C
305     DMCompositeGetNumberDM - Get's the number of DM objects in the DMComposite
306        representation.
307 
308     Not Collective
309 
310     Input Parameter:
311 .    dm - the packer object
312 
313     Output Parameter:
314 .     nDM - the number of DMs
315 
316     Level: beginner
317 
318 @*/
319 PetscErrorCode  DMCompositeGetNumberDM(DM dm,PetscInt *nDM)
320 {
321   DM_Composite *com = (DM_Composite*)dm->data;
322   PetscFunctionBegin;
323   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
324   *nDM = com->nDM;
325   PetscFunctionReturn(0);
326 }
327 
328 
329 #undef __FUNCT__
330 #define __FUNCT__ "DMCompositeGetAccess"
331 /*@C
332     DMCompositeGetAccess - Allows one to access the individual packed vectors in their global
333        representation.
334 
335     Collective on DMComposite
336 
337     Input Parameter:
338 +    dm - the packer object
339 .    gvec - the global vector
340 -    ... - the individual sequential or parallel objects (arrays or vectors)
341 
342     Notes: Use DMCompositeRestoreAccess() to return the vectors when you no longer need them
343 
344     Level: advanced
345 
346 @*/
347 PetscErrorCode  DMCompositeGetAccess(DM dm,Vec gvec,...)
348 {
349   va_list                Argp;
350   PetscErrorCode         ierr;
351   struct DMCompositeLink *next;
352   DM_Composite           *com = (DM_Composite*)dm->data;
353 
354   PetscFunctionBegin;
355   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
356   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
357   next = com->next;
358   if (!com->setup) {
359     ierr = DMSetUp(dm);CHKERRQ(ierr);
360   }
361 
362   /* loop over packed objects, handling one at at time */
363   va_start(Argp,gvec);
364   while (next) {
365     if (next->type == DMCOMPOSITE_ARRAY) {
366       PetscScalar **array;
367       array = va_arg(Argp, PetscScalar**);
368       ierr  = DMCompositeGetAccess_Array(dm,next,gvec,array);CHKERRQ(ierr);
369     } else if (next->type == DMCOMPOSITE_DM) {
370       Vec *vec;
371       vec  = va_arg(Argp, Vec*);
372       ierr = DMCompositeGetAccess_DM(dm,next,gvec,vec);CHKERRQ(ierr);
373     } else {
374       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
375     }
376     next = next->next;
377   }
378   va_end(Argp);
379   PetscFunctionReturn(0);
380 }
381 
382 #undef __FUNCT__
383 #define __FUNCT__ "DMCompositeRestoreAccess"
384 /*@C
385     DMCompositeRestoreAccess - Returns the vectors obtained with DMCompositeGetAccess()
386        representation.
387 
388     Collective on DMComposite
389 
390     Input Parameter:
391 +    dm - the packer object
392 .    gvec - the global vector
393 -    ... - the individual sequential or parallel objects (arrays or vectors)
394 
395     Level: advanced
396 
397 .seealso  DMCompositeAddArray(), DMCompositeAddDM(), DMCreateGlobalVector(),
398          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeScatter(),
399          DMCompositeRestoreAccess(), DMCompositeGetAccess()
400 
401 @*/
402 PetscErrorCode  DMCompositeRestoreAccess(DM dm,Vec gvec,...)
403 {
404   va_list                Argp;
405   PetscErrorCode         ierr;
406   struct DMCompositeLink *next;
407   DM_Composite           *com = (DM_Composite*)dm->data;
408 
409   PetscFunctionBegin;
410   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
411   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
412   next = com->next;
413   if (!com->setup) {
414     ierr = DMSetUp(dm);CHKERRQ(ierr);
415   }
416 
417   /* loop over packed objects, handling one at at time */
418   va_start(Argp,gvec);
419   while (next) {
420     if (next->type == DMCOMPOSITE_ARRAY) {
421       PetscScalar **array;
422       array = va_arg(Argp, PetscScalar**);
423       ierr  = DMCompositeRestoreAccess_Array(dm,next,gvec,array);CHKERRQ(ierr);
424     } else if (next->type == DMCOMPOSITE_DM) {
425       Vec *vec;
426       vec  = va_arg(Argp, Vec*);
427       ierr = DMCompositeRestoreAccess_DM(dm,next,gvec,vec);CHKERRQ(ierr);
428     } else {
429       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
430     }
431     next = next->next;
432   }
433   va_end(Argp);
434   PetscFunctionReturn(0);
435 }
436 
437 #undef __FUNCT__
438 #define __FUNCT__ "DMCompositeScatter"
439 /*@C
440     DMCompositeScatter - Scatters from a global packed vector into its individual local vectors
441 
442     Collective on DMComposite
443 
444     Input Parameter:
445 +    dm - the packer object
446 .    gvec - the global vector
447 -    ... - the individual sequential objects (arrays or vectors), PETSC_NULL for those that are not needed
448 
449     Level: advanced
450 
451 .seealso DMDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCreateGlobalVector(),
452          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
453          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
454 
455 @*/
456 PetscErrorCode  DMCompositeScatter(DM dm,Vec gvec,...)
457 {
458   va_list                Argp;
459   PetscErrorCode         ierr;
460   struct DMCompositeLink *next;
461   PetscInt               cnt;
462   DM_Composite           *com = (DM_Composite*)dm->data;
463 
464   PetscFunctionBegin;
465   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
466   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
467   if (!com->setup) {
468     ierr = DMSetUp(dm);CHKERRQ(ierr);
469   }
470 
471   /* loop over packed objects, handling one at at time */
472   va_start(Argp,gvec);
473   for (cnt=3,next=com->next; next; cnt++,next=next->next) {
474     if (next->type == DMCOMPOSITE_ARRAY) {
475       PetscScalar *array;
476       array = va_arg(Argp, PetscScalar*);
477       if (array) PetscValidScalarPointer(array,cnt);
478       PetscValidLogicalCollectiveBool(dm,!!array,cnt);
479       if (!array) continue;
480       ierr = DMCompositeScatter_Array(dm,next,gvec,array);CHKERRQ(ierr);
481     } else if (next->type == DMCOMPOSITE_DM) {
482       Vec vec;
483       vec = va_arg(Argp, Vec);
484       if (!vec) continue;
485       PetscValidHeaderSpecific(vec,VEC_CLASSID,cnt);
486       ierr = DMCompositeScatter_DM(dm,next,gvec,vec);CHKERRQ(ierr);
487     } else {
488       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
489     }
490   }
491   va_end(Argp);
492   PetscFunctionReturn(0);
493 }
494 
495 #undef __FUNCT__
496 #define __FUNCT__ "DMCompositeGather"
497 /*@C
498     DMCompositeGather - Gathers into a global packed vector from its individual local vectors
499 
500     Collective on DMComposite
501 
502     Input Parameter:
503 +    dm - the packer object
504 .    gvec - the global vector
505 -    ... - the individual sequential objects (arrays or vectors), PETSC_NULL for any that are not needed
506 
507     Level: advanced
508 
509 .seealso DMDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCreateGlobalVector(),
510          DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
511          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
512 
513 @*/
514 PetscErrorCode  DMCompositeGather(DM dm,Vec gvec,InsertMode imode,...)
515 {
516   va_list                Argp;
517   PetscErrorCode         ierr;
518   struct DMCompositeLink *next;
519   DM_Composite           *com = (DM_Composite*)dm->data;
520   PetscInt               cnt;
521 
522   PetscFunctionBegin;
523   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
524   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
525   if (!com->setup) {
526     ierr = DMSetUp(dm);CHKERRQ(ierr);
527   }
528 
529   /* loop over packed objects, handling one at at time */
530   va_start(Argp,imode);
531   for (cnt=3,next=com->next; next; cnt++,next=next->next) {
532     if (next->type == DMCOMPOSITE_ARRAY) {
533       PetscScalar *array;
534       array = va_arg(Argp, PetscScalar*);
535       if (!array) continue;
536       PetscValidScalarPointer(array,cnt);
537       ierr  = DMCompositeGather_Array(dm,next,gvec,imode,array);CHKERRQ(ierr);
538     } else if (next->type == DMCOMPOSITE_DM) {
539       Vec vec;
540       vec = va_arg(Argp, Vec);
541       if (!vec) continue;
542       PetscValidHeaderSpecific(vec,VEC_CLASSID,cnt);
543       ierr = DMCompositeGather_DM(dm,next,gvec,imode,vec);CHKERRQ(ierr);
544     } else {
545       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
546     }
547   }
548   va_end(Argp);
549   PetscFunctionReturn(0);
550 }
551 
552 #undef __FUNCT__
553 #define __FUNCT__ "DMCompositeAddArray"
554 /*@C
555     DMCompositeAddArray - adds an "redundant" array to a DMComposite. The array values will
556        be stored in part of the array on process orank.
557 
558     Collective on DMComposite
559 
560     Input Parameter:
561 +    dm - the packer object
562 .    orank - the process on which the array entries officially live, this number must be
563              the same on all processes.
564 -    n - the length of the array
565 
566     Level: advanced
567 
568 .seealso DMDestroy(), DMCompositeGather(), DMCompositeAddDM(), DMCreateGlobalVector(),
569          DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
570          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
571 
572 @*/
573 PetscErrorCode  DMCompositeAddArray(DM dm,PetscMPIInt orank,PetscInt n)
574 {
575   struct DMCompositeLink *mine,*next;
576   PetscErrorCode         ierr;
577   PetscMPIInt            rank;
578   DM_Composite           *com = (DM_Composite*)dm->data;
579 
580   PetscFunctionBegin;
581   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
582   next = com->next;
583   if (com->setup) {
584     SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"Cannot add an array once you have used the DMComposite");
585   }
586 #if defined(PETSC_USE_DEBUG)
587   {
588     PetscMPIInt orankmax;
589     ierr = MPI_Allreduce(&orank,&orankmax,1,MPI_INT,MPI_MAX,((PetscObject)dm)->comm);CHKERRQ(ierr);
590     if (orank != orankmax) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"orank %d must be equal on all processes, another process has value %d",orank,orankmax);
591   }
592 #endif
593 
594   ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
595   /* create new link */
596   ierr                = PetscNew(struct DMCompositeLink,&mine);CHKERRQ(ierr);
597   mine->nlocal        = n;
598   mine->n             = (rank == orank) ? n : 0;
599   mine->rank          = orank;
600   mine->dm            = PETSC_NULL;
601   mine->type          = DMCOMPOSITE_ARRAY;
602   mine->next          = PETSC_NULL;
603   if (rank == mine->rank) {com->n += n;com->nmine++;}
604 
605   /* add to end of list */
606   if (!next) {
607     com->next = mine;
608   } else {
609     while (next->next) next = next->next;
610     next->next = mine;
611   }
612   com->nredundant++;
613   PetscFunctionReturn(0);
614 }
615 
616 #undef __FUNCT__
617 #define __FUNCT__ "DMCompositeAddDM"
618 /*@C
619     DMCompositeAddDM - adds a DM  vector to a DMComposite
620 
621     Collective on DMComposite
622 
623     Input Parameter:
624 +    dm - the packer object
625 -    dm - the DM object, if the DM is a da you will need to caste it with a (DM)
626 
627     Level: advanced
628 
629 .seealso DMDestroy(), DMCompositeGather(), DMCompositeAddDM(), DMCreateGlobalVector(),
630          DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
631          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
632 
633 @*/
634 PetscErrorCode  DMCompositeAddDM(DM dmc,DM dm)
635 {
636   PetscErrorCode         ierr;
637   PetscInt               n,nlocal;
638   struct DMCompositeLink *mine,*next;
639   Vec                    global,local;
640   DM_Composite           *com = (DM_Composite*)dmc->data;
641 
642   PetscFunctionBegin;
643   PetscValidHeaderSpecific(dmc,DM_CLASSID,1);
644   PetscValidHeaderSpecific(dm,DM_CLASSID,2);
645   next = com->next;
646   if (com->setup) SETERRQ(((PetscObject)dmc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Cannot add a DM once you have used the DMComposite");
647 
648   /* create new link */
649   ierr = PetscNew(struct DMCompositeLink,&mine);CHKERRQ(ierr);
650   ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
651   ierr = DMGetGlobalVector(dm,&global);CHKERRQ(ierr);
652   ierr = VecGetLocalSize(global,&n);CHKERRQ(ierr);
653   ierr = DMRestoreGlobalVector(dm,&global);CHKERRQ(ierr);
654   ierr = DMGetLocalVector(dm,&local);CHKERRQ(ierr);
655   ierr = VecGetSize(local,&nlocal);CHKERRQ(ierr);
656   ierr = DMRestoreLocalVector(dm,&local);CHKERRQ(ierr);
657   mine->n      = n;
658   mine->nlocal = nlocal;
659   mine->dm     = dm;
660   mine->type   = DMCOMPOSITE_DM;
661   mine->next   = PETSC_NULL;
662   com->n       += n;
663 
664   /* add to end of list */
665   if (!next) {
666     com->next = mine;
667   } else {
668     while (next->next) next = next->next;
669     next->next = mine;
670   }
671   com->nDM++;
672   com->nmine++;
673   PetscFunctionReturn(0);
674 }
675 
676 extern PetscErrorCode  VecView_MPI(Vec,PetscViewer);
677 EXTERN_C_BEGIN
678 #undef __FUNCT__
679 #define __FUNCT__ "VecView_DMComposite"
680 PetscErrorCode  VecView_DMComposite(Vec gvec,PetscViewer viewer)
681 {
682   DM                     dm;
683   PetscErrorCode         ierr;
684   struct DMCompositeLink *next;
685   PetscBool              isdraw;
686   DM_Composite           *com;
687 
688   PetscFunctionBegin;
689   ierr = PetscObjectQuery((PetscObject)gvec,"DM",(PetscObject*)&dm);CHKERRQ(ierr);
690   if (!dm) SETERRQ(((PetscObject)gvec)->comm,PETSC_ERR_ARG_WRONG,"Vector not generated from a DMComposite");
691   com = (DM_Composite*)dm->data;
692   next = com->next;
693 
694   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
695   if (!isdraw) {
696     /* do I really want to call this? */
697     ierr = VecView_MPI(gvec,viewer);CHKERRQ(ierr);
698   } else {
699     PetscInt cnt = 0;
700 
701     /* loop over packed objects, handling one at at time */
702     while (next) {
703       if (next->type == DMCOMPOSITE_ARRAY) {
704 	PetscScalar *array;
705 	ierr  = DMCompositeGetAccess_Array(dm,next,gvec,&array);CHKERRQ(ierr);
706 
707 	/*skip it for now */
708       } else if (next->type == DMCOMPOSITE_DM) {
709 	Vec      vec;
710         PetscInt bs;
711 
712 	ierr = DMCompositeGetAccess_DM(dm,next,gvec,&vec);CHKERRQ(ierr);
713 	ierr = VecView(vec,viewer);CHKERRQ(ierr);
714         ierr = VecGetBlockSize(vec,&bs);CHKERRQ(ierr);
715 	ierr = DMCompositeRestoreAccess_DM(dm,next,gvec,&vec);CHKERRQ(ierr);
716         ierr = PetscViewerDrawBaseAdd(viewer,bs);CHKERRQ(ierr);
717         cnt += bs;
718       } else {
719 	SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
720       }
721       next = next->next;
722     }
723     ierr = PetscViewerDrawBaseAdd(viewer,-cnt);CHKERRQ(ierr);
724   }
725   PetscFunctionReturn(0);
726 }
727 EXTERN_C_END
728 
729 
730 #undef __FUNCT__
731 #define __FUNCT__ "DMCreateGlobalVector_Composite"
732 PetscErrorCode  DMCreateGlobalVector_Composite(DM dm,Vec *gvec)
733 {
734   PetscErrorCode         ierr;
735   DM_Composite           *com = (DM_Composite*)dm->data;
736 
737   PetscFunctionBegin;
738   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
739   if (!com->setup) {
740     ierr = DMSetUp(dm);CHKERRQ(ierr);
741   }
742   ierr = VecCreateMPI(((PetscObject)dm)->comm,com->n,com->N,gvec);CHKERRQ(ierr);
743   ierr = PetscObjectCompose((PetscObject)*gvec,"DM",(PetscObject)dm);CHKERRQ(ierr);
744   ierr = VecSetOperation(*gvec,VECOP_VIEW,(void(*)(void))VecView_DMComposite);CHKERRQ(ierr);
745   PetscFunctionReturn(0);
746 }
747 
748 #undef __FUNCT__
749 #define __FUNCT__ "DMCreateLocalVector_Composite"
750 PetscErrorCode  DMCreateLocalVector_Composite(DM dm,Vec *lvec)
751 {
752   PetscErrorCode         ierr;
753   DM_Composite           *com = (DM_Composite*)dm->data;
754 
755   PetscFunctionBegin;
756   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
757   if (!com->setup) {
758     ierr = DMSetUp(dm);CHKERRQ(ierr);
759   }
760   ierr = VecCreateSeq(((PetscObject)dm)->comm,com->nghost,lvec);CHKERRQ(ierr);
761   ierr = PetscObjectCompose((PetscObject)*lvec,"DM",(PetscObject)dm);CHKERRQ(ierr);
762   PetscFunctionReturn(0);
763 }
764 
765 #undef __FUNCT__
766 #define __FUNCT__ "DMCompositeGetISLocalToGlobalMappings"
767 /*@C
768     DMCompositeGetISLocalToGlobalMappings - gets an ISLocalToGlobalMapping for each DM/array in the DMComposite, maps to the composite global space
769 
770     Collective on DM
771 
772     Input Parameter:
773 .    dm - the packer object
774 
775     Output Parameters:
776 .    ltogs - the individual mappings for each packed vector/array. Note that this includes
777            all the ghost points that individual ghosted DMDA's may have. Also each process has an
778            mapping for EACH redundant array (not just the local redundant arrays).
779 
780     Level: advanced
781 
782     Notes:
783        Each entry of ltogs should be destroyed with ISLocalToGlobalMappingDestroy(), the ltogs array should be freed with PetscFree().
784 
785 .seealso DMDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCreateGlobalVector(),
786          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetAccess(), DMCompositeScatter(),
787          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(),DMCompositeGetEntries()
788 
789 @*/
790 PetscErrorCode  DMCompositeGetISLocalToGlobalMappings(DM dm,ISLocalToGlobalMapping **ltogs)
791 {
792   PetscErrorCode         ierr;
793   PetscInt               i,*idx,n,cnt;
794   struct DMCompositeLink *next;
795   PetscMPIInt            rank;
796   DM_Composite           *com = (DM_Composite*)dm->data;
797 
798   PetscFunctionBegin;
799   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
800   ierr = PetscMalloc((com->nDM+com->nredundant)*sizeof(ISLocalToGlobalMapping),ltogs);CHKERRQ(ierr);
801   next = com->next;
802   ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
803 
804   /* loop over packed objects, handling one at at time */
805   cnt = 0;
806   while (next) {
807     if (next->type == DMCOMPOSITE_ARRAY) {
808       ierr = PetscMalloc(next->nlocal*sizeof(PetscInt),&idx);CHKERRQ(ierr);
809       if (rank == next->rank) {
810         for (i=0; i<next->nlocal; i++) idx[i] = next->grstart + i;
811       }
812       ierr = MPI_Bcast(idx,next->nlocal,MPIU_INT,next->rank,((PetscObject)dm)->comm);CHKERRQ(ierr);
813       ierr = ISLocalToGlobalMappingCreate(((PetscObject)dm)->comm,next->nlocal,idx,PETSC_OWN_POINTER,&(*ltogs)[cnt]);CHKERRQ(ierr);
814     } else if (next->type == DMCOMPOSITE_DM) {
815       ISLocalToGlobalMapping ltog;
816       PetscMPIInt            size;
817       const PetscInt         *suboff,*indices;
818       Vec                    global;
819 
820       /* Get sub-DM global indices for each local dof */
821       ierr = DMGetLocalToGlobalMapping(next->dm,&ltog);CHKERRQ(ierr);
822       ierr = ISLocalToGlobalMappingGetSize(ltog,&n);CHKERRQ(ierr);
823       ierr = ISLocalToGlobalMappingGetIndices(ltog,&indices);CHKERRQ(ierr);
824       ierr = PetscMalloc(n*sizeof(PetscInt),&idx);CHKERRQ(ierr);
825 
826       /* Get the offsets for the sub-DM global vector */
827       ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
828       ierr = VecGetOwnershipRanges(global,&suboff);CHKERRQ(ierr);
829       ierr = MPI_Comm_size(((PetscObject)global)->comm,&size);CHKERRQ(ierr);
830 
831       /* Shift the sub-DM definition of the global space to the composite global space */
832       for (i=0; i<n; i++) {
833         PetscInt subi = indices[i],lo = 0,hi = size,t;
834         /* Binary search to find which rank owns subi */
835         while (hi-lo > 1) {
836           t = lo + (hi-lo)/2;
837           if (suboff[t] > subi) hi = t;
838           else                  lo = t;
839         }
840         idx[i] = subi - suboff[lo] + next->grstarts[lo];
841       }
842       ierr = ISLocalToGlobalMappingRestoreIndices(ltog,&indices);CHKERRQ(ierr);
843       ierr = ISLocalToGlobalMappingCreate(((PetscObject)dm)->comm,n,idx,PETSC_OWN_POINTER,&(*ltogs)[cnt]);CHKERRQ(ierr);
844       ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
845     } else SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
846     next = next->next;
847     cnt++;
848   }
849   PetscFunctionReturn(0);
850 }
851 
852 #undef __FUNCT__
853 #define __FUNCT__ "DMCompositeGetLocalISs"
854 /*@C
855    DMCompositeGetLocalISs - Gets index sets for each DM/array component of a composite local vector
856 
857    Not Collective
858 
859    Input Arguments:
860 . dm - composite DM
861 
862    Output Arguments:
863 . is - array of serial index sets for each each component of the DMComposite
864 
865    Level: intermediate
866 
867    Notes:
868    At present, a composite local vector does not normally exist.  This function is used to provide index sets for
869    MatGetLocalSubMatrix().  In the future, the scatters for each entry in the DMComposite may be be merged into a single
870    scatter to a composite local vector.
871 
872    To get the composite global indices at all local points (including ghosts), use DMCompositeGetISLocalToGlobalMappings().
873 
874    To get index sets for pieces of the composite global vector, use DMCompositeGetGlobalISs().
875 
876    Each returned IS should be destroyed with ISDestroy(), the array should be freed with PetscFree().
877 
878 .seealso: DMCompositeGetGlobalISs(), DMCompositeGetISLocalToGlobalMappings(), MatGetLocalSubMatrix(), MatCreateLocalRef()
879 @*/
880 PetscErrorCode  DMCompositeGetLocalISs(DM dm,IS **is)
881 {
882   PetscErrorCode         ierr;
883   DM_Composite           *com = (DM_Composite*)dm->data;
884   struct DMCompositeLink *link;
885   PetscInt cnt,start;
886 
887   PetscFunctionBegin;
888   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
889   PetscValidPointer(is,2);
890   ierr = PetscMalloc(com->nmine*sizeof(IS),is);CHKERRQ(ierr);
891   for (cnt=0,start=0,link=com->next; link; start+=link->nlocal,cnt++,link=link->next) {
892     ierr = ISCreateStride(PETSC_COMM_SELF,link->nlocal,start,1,&(*is)[cnt]);CHKERRQ(ierr);
893     if (link->type == DMCOMPOSITE_DM) {
894       PetscInt bs;
895       ierr = DMGetBlockSize(link->dm,&bs);CHKERRQ(ierr);
896       ierr = ISSetBlockSize((*is)[cnt],bs);CHKERRQ(ierr);
897     }
898   }
899   PetscFunctionReturn(0);
900 }
901 
902 #undef __FUNCT__
903 #define __FUNCT__ "DMCompositeGetGlobalISs"
904 /*@C
905     DMCompositeGetGlobalISs - Gets the index sets for each composed object
906 
907     Collective on DMComposite
908 
909     Input Parameter:
910 .    dm - the packer object
911 
912     Output Parameters:
913 .    is - the array of index sets
914 
915     Level: advanced
916 
917     Notes:
918        The is entries should be destroyed with ISDestroy(), the is array should be freed with PetscFree()
919 
920        These could be used to extract a subset of vector entries for a "multi-physics" preconditioner
921 
922        Use DMCompositeGetLocalISs() for index sets in the packed local numbering, and
923        DMCompositeGetISLocalToGlobalMappings() for to map local sub-DM (including ghost) indices to packed global
924        indices.
925 
926 .seealso DMDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCreateGlobalVector(),
927          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetAccess(), DMCompositeScatter(),
928          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(),DMCompositeGetEntries()
929 
930 @*/
931 
932 PetscErrorCode  DMCompositeGetGlobalISs(DM dm,IS *is[])
933 {
934   PetscErrorCode         ierr;
935   PetscInt               cnt = 0,*idx,i;
936   struct DMCompositeLink *next;
937   PetscMPIInt            rank;
938   DM_Composite           *com = (DM_Composite*)dm->data;
939 
940   PetscFunctionBegin;
941   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
942   ierr = PetscMalloc((com->nDM+com->nredundant)*sizeof(IS),is);CHKERRQ(ierr);
943   next = com->next;
944   ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
945 
946   /* loop over packed objects, handling one at at time */
947   while (next) {
948     ierr = PetscMalloc(next->n*sizeof(PetscInt),&idx);CHKERRQ(ierr);
949     for (i=0; i<next->n; i++) idx[i] = next->grstart + i;
950     ierr = ISCreateGeneral(((PetscObject)dm)->comm,next->n,idx,PETSC_OWN_POINTER,&(*is)[cnt]);CHKERRQ(ierr);
951     cnt++;
952     next = next->next;
953   }
954   PetscFunctionReturn(0);
955 }
956 
957 /* -------------------------------------------------------------------------------------*/
958 #undef __FUNCT__
959 #define __FUNCT__ "DMCompositeGetLocalVectors_Array"
960 PetscErrorCode DMCompositeGetLocalVectors_Array(DM dm,struct DMCompositeLink *mine,PetscScalar **array)
961 {
962   PetscErrorCode ierr;
963   PetscFunctionBegin;
964   if (array) {
965     ierr = PetscMalloc(mine->nlocal*sizeof(PetscScalar),array);CHKERRQ(ierr);
966   }
967   PetscFunctionReturn(0);
968 }
969 
970 #undef __FUNCT__
971 #define __FUNCT__ "DMCompositeGetLocalVectors_DM"
972 PetscErrorCode DMCompositeGetLocalVectors_DM(DM dm,struct DMCompositeLink *mine,Vec *local)
973 {
974   PetscErrorCode ierr;
975   PetscFunctionBegin;
976   if (local) {
977     ierr = DMGetLocalVector(mine->dm,local);CHKERRQ(ierr);
978   }
979   PetscFunctionReturn(0);
980 }
981 
982 #undef __FUNCT__
983 #define __FUNCT__ "DMCompositeRestoreLocalVectors_Array"
984 PetscErrorCode DMCompositeRestoreLocalVectors_Array(DM dm,struct DMCompositeLink *mine,PetscScalar **array)
985 {
986   PetscErrorCode ierr;
987   PetscFunctionBegin;
988   if (array) {
989     ierr = PetscFree(*array);CHKERRQ(ierr);
990   }
991   PetscFunctionReturn(0);
992 }
993 
994 #undef __FUNCT__
995 #define __FUNCT__ "DMCompositeRestoreLocalVectors_DM"
996 PetscErrorCode DMCompositeRestoreLocalVectors_DM(DM dm,struct DMCompositeLink *mine,Vec *local)
997 {
998   PetscErrorCode ierr;
999   PetscFunctionBegin;
1000   if (local) {
1001     ierr = DMRestoreLocalVector(mine->dm,local);CHKERRQ(ierr);
1002   }
1003   PetscFunctionReturn(0);
1004 }
1005 
1006 #undef __FUNCT__
1007 #define __FUNCT__ "DMCompositeGetLocalVectors"
1008 /*@C
1009     DMCompositeGetLocalVectors - Gets local vectors and arrays for each part of a DMComposite.
1010        Use DMCompositeRestoreLocalVectors() to return them.
1011 
1012     Not Collective
1013 
1014     Input Parameter:
1015 .    dm - the packer object
1016 
1017     Output Parameter:
1018 .    ... - the individual sequential objects (arrays or vectors)
1019 
1020     Level: advanced
1021 
1022 .seealso DMDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCreateGlobalVector(),
1023          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
1024          DMCompositeRestoreLocalVectors(), DMCompositeScatter(), DMCompositeGetEntries()
1025 
1026 @*/
1027 PetscErrorCode  DMCompositeGetLocalVectors(DM dm,...)
1028 {
1029   va_list                Argp;
1030   PetscErrorCode         ierr;
1031   struct DMCompositeLink *next;
1032   DM_Composite           *com = (DM_Composite*)dm->data;
1033 
1034   PetscFunctionBegin;
1035   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1036   next = com->next;
1037   /* loop over packed objects, handling one at at time */
1038   va_start(Argp,dm);
1039   while (next) {
1040     if (next->type == DMCOMPOSITE_ARRAY) {
1041       PetscScalar **array;
1042       array = va_arg(Argp, PetscScalar**);
1043       ierr = DMCompositeGetLocalVectors_Array(dm,next,array);CHKERRQ(ierr);
1044     } else if (next->type == DMCOMPOSITE_DM) {
1045       Vec *vec;
1046       vec = va_arg(Argp, Vec*);
1047       ierr = DMCompositeGetLocalVectors_DM(dm,next,vec);CHKERRQ(ierr);
1048     } else {
1049       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1050     }
1051     next = next->next;
1052   }
1053   va_end(Argp);
1054   PetscFunctionReturn(0);
1055 }
1056 
1057 #undef __FUNCT__
1058 #define __FUNCT__ "DMCompositeRestoreLocalVectors"
1059 /*@C
1060     DMCompositeRestoreLocalVectors - Restores local vectors and arrays for each part of a DMComposite.
1061 
1062     Not Collective
1063 
1064     Input Parameter:
1065 .    dm - the packer object
1066 
1067     Output Parameter:
1068 .    ... - the individual sequential objects (arrays or vectors)
1069 
1070     Level: advanced
1071 
1072 .seealso DMDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCreateGlobalVector(),
1073          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
1074          DMCompositeGetLocalVectors(), DMCompositeScatter(), DMCompositeGetEntries()
1075 
1076 @*/
1077 PetscErrorCode  DMCompositeRestoreLocalVectors(DM dm,...)
1078 {
1079   va_list                Argp;
1080   PetscErrorCode         ierr;
1081   struct DMCompositeLink *next;
1082   DM_Composite           *com = (DM_Composite*)dm->data;
1083 
1084   PetscFunctionBegin;
1085   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1086   next = com->next;
1087   /* loop over packed objects, handling one at at time */
1088   va_start(Argp,dm);
1089   while (next) {
1090     if (next->type == DMCOMPOSITE_ARRAY) {
1091       PetscScalar **array;
1092       array = va_arg(Argp, PetscScalar**);
1093       ierr = DMCompositeRestoreLocalVectors_Array(dm,next,array);CHKERRQ(ierr);
1094     } else if (next->type == DMCOMPOSITE_DM) {
1095       Vec *vec;
1096       vec = va_arg(Argp, Vec*);
1097       ierr = DMCompositeRestoreLocalVectors_DM(dm,next,vec);CHKERRQ(ierr);
1098     } else {
1099       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1100     }
1101     next = next->next;
1102   }
1103   va_end(Argp);
1104   PetscFunctionReturn(0);
1105 }
1106 
1107 /* -------------------------------------------------------------------------------------*/
1108 #undef __FUNCT__
1109 #define __FUNCT__ "DMCompositeGetEntries_Array"
1110 PetscErrorCode DMCompositeGetEntries_Array(DM dm,struct DMCompositeLink *mine,PetscInt *n)
1111 {
1112   PetscFunctionBegin;
1113   if (n) *n = mine->nlocal;
1114   PetscFunctionReturn(0);
1115 }
1116 
1117 #undef __FUNCT__
1118 #define __FUNCT__ "DMCompositeGetEntries_DM"
1119 PetscErrorCode DMCompositeGetEntries_DM(DM dmi,struct DMCompositeLink *mine,DM *dm)
1120 {
1121   PetscFunctionBegin;
1122   if (dm) *dm = mine->dm;
1123   PetscFunctionReturn(0);
1124 }
1125 
1126 #undef __FUNCT__
1127 #define __FUNCT__ "DMCompositeGetEntries"
1128 /*@C
1129     DMCompositeGetEntries - Gets the DM, redundant size, etc for each entry in a DMComposite.
1130 
1131     Not Collective
1132 
1133     Input Parameter:
1134 .    dm - the packer object
1135 
1136     Output Parameter:
1137 .    ... - the individual entries, DMs or integer sizes)
1138 
1139     Level: advanced
1140 
1141 .seealso DMDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCreateGlobalVector(),
1142          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
1143          DMCompositeRestoreLocalVectors(), DMCompositeGetLocalVectors(),  DMCompositeScatter(),
1144          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors()
1145 
1146 @*/
1147 PetscErrorCode  DMCompositeGetEntries(DM dm,...)
1148 {
1149   va_list                Argp;
1150   PetscErrorCode         ierr;
1151   struct DMCompositeLink *next;
1152   DM_Composite           *com = (DM_Composite*)dm->data;
1153 
1154   PetscFunctionBegin;
1155   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1156   next = com->next;
1157   /* loop over packed objects, handling one at at time */
1158   va_start(Argp,dm);
1159   while (next) {
1160     if (next->type == DMCOMPOSITE_ARRAY) {
1161       PetscInt *n;
1162       n = va_arg(Argp, PetscInt*);
1163       ierr = DMCompositeGetEntries_Array(dm,next,n);CHKERRQ(ierr);
1164     } else if (next->type == DMCOMPOSITE_DM) {
1165       DM *dmn;
1166       dmn = va_arg(Argp, DM*);
1167       ierr = DMCompositeGetEntries_DM(dm,next,dmn);CHKERRQ(ierr);
1168     } else {
1169       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1170     }
1171     next = next->next;
1172   }
1173   va_end(Argp);
1174   PetscFunctionReturn(0);
1175 }
1176 
1177 #undef __FUNCT__
1178 #define __FUNCT__ "DMRefine_Composite"
1179 PetscErrorCode  DMRefine_Composite(DM dmi,MPI_Comm comm,DM *fine)
1180 {
1181   PetscErrorCode         ierr;
1182   struct DMCompositeLink *next;
1183   DM_Composite           *com = (DM_Composite*)dmi->data;
1184   DM                     dm;
1185 
1186   PetscFunctionBegin;
1187   PetscValidHeaderSpecific(dmi,DM_CLASSID,1);
1188   next = com->next;
1189   ierr = DMCompositeCreate(comm,fine);CHKERRQ(ierr);
1190 
1191   /* loop over packed objects, handling one at at time */
1192   while (next) {
1193     if (next->type == DMCOMPOSITE_ARRAY) {
1194       ierr = DMCompositeAddArray(*fine,next->rank,next->nlocal);CHKERRQ(ierr);
1195     } else if (next->type == DMCOMPOSITE_DM) {
1196       ierr = DMRefine(next->dm,comm,&dm);CHKERRQ(ierr);
1197       ierr = DMCompositeAddDM(*fine,dm);CHKERRQ(ierr);
1198       ierr = PetscObjectDereference((PetscObject)dm);CHKERRQ(ierr);
1199     } else {
1200       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1201     }
1202     next = next->next;
1203   }
1204   PetscFunctionReturn(0);
1205 }
1206 
1207 #undef __FUNCT__
1208 #define __FUNCT__ "DMCoarsen_Composite"
1209 PetscErrorCode  DMCoarsen_Composite(DM dmi,MPI_Comm comm,DM *fine)
1210 {
1211   PetscErrorCode         ierr;
1212   struct DMCompositeLink *next;
1213   DM_Composite           *com = (DM_Composite*)dmi->data;
1214   DM                     dm;
1215 
1216   PetscFunctionBegin;
1217   PetscValidHeaderSpecific(dmi,DM_CLASSID,1);
1218   next = com->next;
1219   ierr = DMCompositeCreate(comm,fine);CHKERRQ(ierr);
1220 
1221   /* loop over packed objects, handling one at at time */
1222   while (next) {
1223     if (next->type == DMCOMPOSITE_ARRAY) {
1224       ierr = DMCompositeAddArray(*fine,next->rank,next->nlocal);CHKERRQ(ierr);
1225     } else if (next->type == DMCOMPOSITE_DM) {
1226       ierr = DMCoarsen(next->dm,comm,&dm);CHKERRQ(ierr);
1227       ierr = DMCompositeAddDM(*fine,dm);CHKERRQ(ierr);
1228       ierr = PetscObjectDereference((PetscObject)dm);CHKERRQ(ierr);
1229     } else {
1230       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1231     }
1232     next = next->next;
1233   }
1234   PetscFunctionReturn(0);
1235 }
1236 
1237 struct MatPackLink {
1238   Mat                A;
1239   struct MatPackLink *next;
1240 };
1241 
1242 struct MatPack {
1243   DM                 right,left;
1244   struct MatPackLink *next;
1245 };
1246 
1247 #undef __FUNCT__
1248 #define __FUNCT__ "MatMultBoth_Shell_Pack"
1249 PetscErrorCode MatMultBoth_Shell_Pack(Mat A,Vec x,Vec y,PetscBool  add)
1250 {
1251   struct MatPack         *mpack;
1252   struct DMCompositeLink *xnext,*ynext;
1253   struct MatPackLink     *anext;
1254   PetscScalar            *xarray,*yarray;
1255   PetscErrorCode         ierr;
1256   PetscInt               i;
1257   Vec                    xglobal,yglobal;
1258   PetscMPIInt            rank;
1259   DM_Composite           *comright;
1260   DM_Composite           *comleft;
1261 
1262   PetscFunctionBegin;
1263   ierr = MatShellGetContext(A,(void**)&mpack);CHKERRQ(ierr);
1264   ierr = MPI_Comm_rank(((PetscObject)mpack->right)->comm,&rank);CHKERRQ(ierr);
1265   comright = (DM_Composite*)mpack->right->data;
1266   comleft = (DM_Composite*)mpack->left->data;
1267   xnext = comright->next;
1268   ynext = comleft->next;
1269   anext = mpack->next;
1270 
1271   while (xnext) {
1272     if (xnext->type == DMCOMPOSITE_ARRAY) {
1273       if (rank == xnext->rank) {
1274         ierr    = VecGetArray(x,&xarray);CHKERRQ(ierr);
1275         ierr    = VecGetArray(y,&yarray);CHKERRQ(ierr);
1276         if (add) {
1277           for (i=0; i<xnext->n; i++) {
1278             yarray[ynext->rstart+i] += xarray[xnext->rstart+i];
1279           }
1280         } else {
1281           ierr    = PetscMemcpy(yarray+ynext->rstart,xarray+xnext->rstart,xnext->n*sizeof(PetscScalar));CHKERRQ(ierr);
1282         }
1283         ierr    = VecRestoreArray(x,&xarray);CHKERRQ(ierr);
1284         ierr    = VecRestoreArray(y,&yarray);CHKERRQ(ierr);
1285       }
1286     } else if (xnext->type == DMCOMPOSITE_DM) {
1287       ierr  = VecGetArray(x,&xarray);CHKERRQ(ierr);
1288       ierr  = VecGetArray(y,&yarray);CHKERRQ(ierr);
1289       ierr  = DMGetGlobalVector(xnext->dm,&xglobal);CHKERRQ(ierr);
1290       ierr  = DMGetGlobalVector(ynext->dm,&yglobal);CHKERRQ(ierr);
1291       ierr  = VecPlaceArray(xglobal,xarray+xnext->rstart);CHKERRQ(ierr);
1292       ierr  = VecPlaceArray(yglobal,yarray+ynext->rstart);CHKERRQ(ierr);
1293       if (add) {
1294         ierr  = MatMultAdd(anext->A,xglobal,yglobal,yglobal);CHKERRQ(ierr);
1295       } else {
1296         ierr  = MatMult(anext->A,xglobal,yglobal);CHKERRQ(ierr);
1297       }
1298       ierr  = VecRestoreArray(x,&xarray);CHKERRQ(ierr);
1299       ierr  = VecRestoreArray(y,&yarray);CHKERRQ(ierr);
1300       ierr  = VecResetArray(xglobal);CHKERRQ(ierr);
1301       ierr  = VecResetArray(yglobal);CHKERRQ(ierr);
1302       ierr  = DMRestoreGlobalVector(xnext->dm,&xglobal);CHKERRQ(ierr);
1303       ierr  = DMRestoreGlobalVector(ynext->dm,&yglobal);CHKERRQ(ierr);
1304       anext = anext->next;
1305     } else {
1306       SETERRQ(((PetscObject)A)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1307     }
1308     xnext = xnext->next;
1309     ynext = ynext->next;
1310   }
1311   PetscFunctionReturn(0);
1312 }
1313 
1314 #undef __FUNCT__
1315 #define __FUNCT__ "MatMultAdd_Shell_Pack"
1316 PetscErrorCode MatMultAdd_Shell_Pack(Mat A,Vec x,Vec y,Vec z)
1317 {
1318   PetscErrorCode ierr;
1319   PetscFunctionBegin;
1320   if (z != y) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_SUP,"Handles y == z only");
1321   ierr = MatMultBoth_Shell_Pack(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
1322   PetscFunctionReturn(0);
1323 }
1324 
1325 #undef __FUNCT__
1326 #define __FUNCT__ "MatMult_Shell_Pack"
1327 PetscErrorCode MatMult_Shell_Pack(Mat A,Vec x,Vec y)
1328 {
1329   PetscErrorCode ierr;
1330   PetscFunctionBegin;
1331   ierr = MatMultBoth_Shell_Pack(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
1332   PetscFunctionReturn(0);
1333 }
1334 
1335 #undef __FUNCT__
1336 #define __FUNCT__ "MatMultTranspose_Shell_Pack"
1337 PetscErrorCode MatMultTranspose_Shell_Pack(Mat A,Vec x,Vec y)
1338 {
1339   struct MatPack         *mpack;
1340   struct DMCompositeLink *xnext,*ynext;
1341   struct MatPackLink     *anext;
1342   PetscScalar            *xarray,*yarray;
1343   PetscErrorCode         ierr;
1344   Vec                    xglobal,yglobal;
1345   PetscMPIInt            rank;
1346   DM_Composite           *comright;
1347   DM_Composite           *comleft;
1348 
1349   PetscFunctionBegin;
1350   ierr  = MatShellGetContext(A,(void**)&mpack);CHKERRQ(ierr);
1351   ierr = MPI_Comm_rank(((PetscObject)mpack->right)->comm,&rank);CHKERRQ(ierr);
1352   comright = (DM_Composite*)mpack->right->data;
1353   comleft = (DM_Composite*)mpack->left->data;
1354   ynext = comright->next;
1355   xnext = comleft->next;
1356   anext = mpack->next;
1357 
1358   while (xnext) {
1359     if (xnext->type == DMCOMPOSITE_ARRAY) {
1360       if (rank == ynext->rank) {
1361         ierr    = VecGetArray(x,&xarray);CHKERRQ(ierr);
1362         ierr    = VecGetArray(y,&yarray);CHKERRQ(ierr);
1363         ierr    = PetscMemcpy(yarray+ynext->rstart,xarray+xnext->rstart,xnext->n*sizeof(PetscScalar));CHKERRQ(ierr);
1364         ierr    = VecRestoreArray(x,&xarray);CHKERRQ(ierr);
1365         ierr    = VecRestoreArray(y,&yarray);CHKERRQ(ierr);
1366       }
1367     } else if (xnext->type == DMCOMPOSITE_DM) {
1368       ierr  = VecGetArray(x,&xarray);CHKERRQ(ierr);
1369       ierr  = VecGetArray(y,&yarray);CHKERRQ(ierr);
1370       ierr  = DMGetGlobalVector(xnext->dm,&xglobal);CHKERRQ(ierr);
1371       ierr  = DMGetGlobalVector(ynext->dm,&yglobal);CHKERRQ(ierr);
1372       ierr  = VecPlaceArray(xglobal,xarray+xnext->rstart);CHKERRQ(ierr);
1373       ierr  = VecPlaceArray(yglobal,yarray+ynext->rstart);CHKERRQ(ierr);
1374       ierr  = MatMultTranspose(anext->A,xglobal,yglobal);CHKERRQ(ierr);
1375       ierr  = VecRestoreArray(x,&xarray);CHKERRQ(ierr);
1376       ierr  = VecRestoreArray(y,&yarray);CHKERRQ(ierr);
1377       ierr  = VecResetArray(xglobal);CHKERRQ(ierr);
1378       ierr  = VecResetArray(yglobal);CHKERRQ(ierr);
1379       ierr  = DMRestoreGlobalVector(xnext->dm,&xglobal);CHKERRQ(ierr);
1380       ierr  = DMRestoreGlobalVector(ynext->dm,&yglobal);CHKERRQ(ierr);
1381       anext = anext->next;
1382     } else {
1383       SETERRQ(((PetscObject)A)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1384     }
1385     xnext = xnext->next;
1386     ynext = ynext->next;
1387   }
1388   PetscFunctionReturn(0);
1389 }
1390 
1391 #undef __FUNCT__
1392 #define __FUNCT__ "MatDestroy_Shell_Pack"
1393 PetscErrorCode MatDestroy_Shell_Pack(Mat A)
1394 {
1395   struct MatPack     *mpack;
1396   struct MatPackLink *anext,*oldanext;
1397   PetscErrorCode     ierr;
1398 
1399   PetscFunctionBegin;
1400   ierr  = MatShellGetContext(A,(void**)&mpack);CHKERRQ(ierr);
1401   anext = mpack->next;
1402 
1403   while (anext) {
1404     ierr     = MatDestroy(&anext->A);CHKERRQ(ierr);
1405     oldanext = anext;
1406     anext    = anext->next;
1407     ierr     = PetscFree(oldanext);CHKERRQ(ierr);
1408   }
1409   ierr = PetscFree(mpack);CHKERRQ(ierr);
1410   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
1411   PetscFunctionReturn(0);
1412 }
1413 
1414 #undef __FUNCT__
1415 #define __FUNCT__ "DMGetInterpolation_Composite"
1416 PetscErrorCode  DMGetInterpolation_Composite(DM coarse,DM fine,Mat *A,Vec *v)
1417 {
1418   PetscErrorCode         ierr;
1419   PetscInt               m,n,M,N;
1420   struct DMCompositeLink *nextc;
1421   struct DMCompositeLink *nextf;
1422   struct MatPackLink     *nextmat,*pnextmat = 0;
1423   struct MatPack         *mpack;
1424   Vec                    gcoarse,gfine;
1425   DM_Composite           *comcoarse = (DM_Composite*)coarse->data;
1426   DM_Composite           *comfine = (DM_Composite*)fine->data;
1427 
1428   PetscFunctionBegin;
1429   PetscValidHeaderSpecific(coarse,DM_CLASSID,1);
1430   PetscValidHeaderSpecific(fine,DM_CLASSID,2);
1431   nextc = comcoarse->next;
1432   nextf = comfine->next;
1433   /* use global vectors only for determining matrix layout */
1434   ierr = DMCreateGlobalVector(coarse,&gcoarse);CHKERRQ(ierr);
1435   ierr = DMCreateGlobalVector(fine,&gfine);CHKERRQ(ierr);
1436   ierr = VecGetLocalSize(gcoarse,&n);CHKERRQ(ierr);
1437   ierr = VecGetLocalSize(gfine,&m);CHKERRQ(ierr);
1438   ierr = VecGetSize(gcoarse,&N);CHKERRQ(ierr);
1439   ierr = VecGetSize(gfine,&M);CHKERRQ(ierr);
1440   ierr = VecDestroy(&gcoarse);CHKERRQ(ierr);
1441   ierr = VecDestroy(&gfine);CHKERRQ(ierr);
1442 
1443   ierr         = PetscNew(struct MatPack,&mpack);CHKERRQ(ierr);
1444   mpack->right = coarse;
1445   mpack->left  = fine;
1446   ierr  = MatCreate(((PetscObject)fine)->comm,A);CHKERRQ(ierr);
1447   ierr  = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
1448   ierr  = MatSetType(*A,MATSHELL);CHKERRQ(ierr);
1449   ierr  = MatShellSetContext(*A,mpack);CHKERRQ(ierr);
1450   ierr  = MatShellSetOperation(*A,MATOP_MULT,(void(*)(void))MatMult_Shell_Pack);CHKERRQ(ierr);
1451   ierr  = MatShellSetOperation(*A,MATOP_MULT_TRANSPOSE,(void(*)(void))MatMultTranspose_Shell_Pack);CHKERRQ(ierr);
1452   ierr  = MatShellSetOperation(*A,MATOP_MULT_ADD,(void(*)(void))MatMultAdd_Shell_Pack);CHKERRQ(ierr);
1453   ierr  = MatShellSetOperation(*A,MATOP_DESTROY,(void(*)(void))MatDestroy_Shell_Pack);CHKERRQ(ierr);
1454 
1455   /* loop over packed objects, handling one at at time */
1456   while (nextc) {
1457     if (nextc->type != nextf->type) SETERRQ(((PetscObject)fine)->comm,PETSC_ERR_ARG_INCOMP,"Two DM have different layout");
1458 
1459     if (nextc->type == DMCOMPOSITE_ARRAY) {
1460       ;
1461     } else if (nextc->type == DMCOMPOSITE_DM) {
1462       ierr          = PetscNew(struct MatPackLink,&nextmat);CHKERRQ(ierr);
1463       nextmat->next = 0;
1464       if (pnextmat) {
1465         pnextmat->next = nextmat;
1466         pnextmat       = nextmat;
1467       } else {
1468         pnextmat    = nextmat;
1469         mpack->next = nextmat;
1470       }
1471       ierr = DMGetInterpolation(nextc->dm,nextf->dm,&nextmat->A,PETSC_NULL);CHKERRQ(ierr);
1472     } else {
1473       SETERRQ(((PetscObject)fine)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1474     }
1475     nextc = nextc->next;
1476     nextf = nextf->next;
1477   }
1478   PetscFunctionReturn(0);
1479 }
1480 
1481 #undef __FUNCT__
1482 #define __FUNCT__ "DMCreateLocalToGlobalMapping_Composite"
1483 static PetscErrorCode DMCreateLocalToGlobalMapping_Composite(DM dm)
1484 {
1485   DM_Composite           *com = (DM_Composite*)dm->data;
1486   ISLocalToGlobalMapping *ltogs;
1487   PetscInt               i;
1488   PetscErrorCode         ierr;
1489 
1490   PetscFunctionBegin;
1491   /* Set the ISLocalToGlobalMapping on the new matrix */
1492   ierr = DMCompositeGetISLocalToGlobalMappings(dm,&ltogs);CHKERRQ(ierr);
1493   ierr = ISLocalToGlobalMappingConcatenate(((PetscObject)dm)->comm,com->nDM+com->nredundant,ltogs,&dm->ltogmap);CHKERRQ(ierr);
1494   for (i=0; i<com->nDM+com->nredundant; i++) {ierr = ISLocalToGlobalMappingDestroy(&ltogs[i]);CHKERRQ(ierr);}
1495   ierr = PetscFree(ltogs);CHKERRQ(ierr);
1496   PetscFunctionReturn(0);
1497 }
1498 
1499 
1500 #undef __FUNCT__
1501 #define __FUNCT__ "DMGetColoring_Composite"
1502 PetscErrorCode  DMGetColoring_Composite(DM dm,ISColoringType ctype,const MatType mtype,ISColoring *coloring)
1503 {
1504   PetscErrorCode         ierr;
1505   PetscInt               n,i,cnt;
1506   ISColoringValue        *colors;
1507   PetscBool              dense = PETSC_FALSE;
1508   ISColoringValue        maxcol = 0;
1509   DM_Composite           *com = (DM_Composite*)dm->data;
1510 
1511   PetscFunctionBegin;
1512   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1513   if (ctype == IS_COLORING_GHOSTED) {
1514     SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Currently you must use -dmmg_iscoloring_type global" );
1515   } else if (ctype == IS_COLORING_GLOBAL) {
1516     n = com->n;
1517   } else SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Unknown ISColoringType");
1518   ierr = PetscMalloc(n*sizeof(ISColoringValue),&colors);CHKERRQ(ierr); /* freed in ISColoringDestroy() */
1519 
1520   ierr = PetscOptionsGetBool(PETSC_NULL,"-dmcomposite_dense_jacobian",&dense,PETSC_NULL);CHKERRQ(ierr);
1521   if (dense) {
1522     for (i=0; i<n; i++) {
1523       colors[i] = (ISColoringValue)(com->rstart + i);
1524     }
1525     maxcol = com->N;
1526   } else {
1527     struct DMCompositeLink *next = com->next;
1528     PetscMPIInt            rank;
1529 
1530     ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
1531     cnt  = 0;
1532     while (next) {
1533       if (next->type == DMCOMPOSITE_ARRAY) {
1534         if (rank == next->rank) {  /* each column gets is own color */
1535           for (i=com->rstart+next->rstart; i<com->rstart+next->rstart+next->n; i++) {
1536             colors[cnt++] = maxcol++;
1537           }
1538         }
1539         ierr = MPI_Bcast(&maxcol,1,MPIU_COLORING_VALUE,next->rank,((PetscObject)dm)->comm);CHKERRQ(ierr);
1540       } else if (next->type == DMCOMPOSITE_DM) {
1541         ISColoring     lcoloring;
1542 
1543         ierr = DMGetColoring(next->dm,IS_COLORING_GLOBAL,mtype,&lcoloring);CHKERRQ(ierr);
1544         for (i=0; i<lcoloring->N; i++) {
1545           colors[cnt++] = maxcol + lcoloring->colors[i];
1546         }
1547         maxcol += lcoloring->n;
1548         ierr = ISColoringDestroy(&lcoloring);CHKERRQ(ierr);
1549       } else SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1550       next = next->next;
1551     }
1552   }
1553   ierr = ISColoringCreate(((PetscObject)dm)->comm,maxcol,n,colors,coloring);CHKERRQ(ierr);
1554   PetscFunctionReturn(0);
1555 }
1556 
1557 #undef __FUNCT__
1558 #define __FUNCT__ "DMGlobalToLocalBegin_Composite"
1559 PetscErrorCode  DMGlobalToLocalBegin_Composite(DM dm,Vec gvec,InsertMode mode,Vec lvec)
1560 {
1561   PetscErrorCode         ierr;
1562   struct DMCompositeLink *next;
1563   PetscInt               cnt = 3;
1564   PetscMPIInt            rank;
1565   PetscScalar            *garray,*larray;
1566   DM_Composite           *com = (DM_Composite*)dm->data;
1567 
1568   PetscFunctionBegin;
1569   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1570   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
1571   next = com->next;
1572   if (!com->setup) {
1573     ierr = DMSetUp(dm);CHKERRQ(ierr);
1574   }
1575   ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
1576   ierr = VecGetArray(gvec,&garray);CHKERRQ(ierr);
1577   ierr = VecGetArray(lvec,&larray);CHKERRQ(ierr);
1578 
1579   /* loop over packed objects, handling one at at time */
1580   while (next) {
1581     if (next->type == DMCOMPOSITE_ARRAY) {
1582       if (rank == next->rank) {
1583         ierr    = PetscMemcpy(larray,garray,next->n*sizeof(PetscScalar));CHKERRQ(ierr);
1584         garray += next->n;
1585       }
1586       /* does not handle ADD_VALUES */
1587       ierr = MPI_Bcast(larray,next->nlocal,MPIU_SCALAR,next->rank,((PetscObject)dm)->comm);CHKERRQ(ierr);
1588     } else if (next->type == DMCOMPOSITE_DM) {
1589       Vec      local,global;
1590       PetscInt N;
1591 
1592       ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
1593       ierr = VecGetLocalSize(global,&N);CHKERRQ(ierr);
1594       ierr = VecPlaceArray(global,garray);CHKERRQ(ierr);
1595       ierr = DMGetLocalVector(next->dm,&local);CHKERRQ(ierr);
1596       ierr = VecPlaceArray(local,larray);CHKERRQ(ierr);
1597       ierr = DMGlobalToLocalBegin(next->dm,global,mode,local);CHKERRQ(ierr);
1598       ierr = DMGlobalToLocalEnd(next->dm,global,mode,local);CHKERRQ(ierr);
1599       ierr = VecResetArray(global);CHKERRQ(ierr);
1600       ierr = VecResetArray(local);CHKERRQ(ierr);
1601       ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
1602       ierr = DMRestoreGlobalVector(next->dm,&local);CHKERRQ(ierr);
1603     } else {
1604       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1605     }
1606     cnt++;
1607     larray += next->nlocal;
1608     next    = next->next;
1609   }
1610 
1611   ierr = VecRestoreArray(gvec,PETSC_NULL);CHKERRQ(ierr);
1612   ierr = VecRestoreArray(lvec,PETSC_NULL);CHKERRQ(ierr);
1613   PetscFunctionReturn(0);
1614 }
1615 
1616 #undef __FUNCT__
1617 #define __FUNCT__ "DMGlobalToLocalEnd_Composite"
1618 PetscErrorCode  DMGlobalToLocalEnd_Composite(DM dm,Vec gvec,InsertMode mode,Vec lvec)
1619 {
1620   PetscFunctionBegin;
1621   PetscFunctionReturn(0);
1622 }
1623 
1624 EXTERN_C_BEGIN
1625 #undef __FUNCT__
1626 #define __FUNCT__ "DMCreate_Composite"
1627 PetscErrorCode  DMCreate_Composite(DM p)
1628 {
1629   PetscErrorCode ierr;
1630   DM_Composite   *com;
1631 
1632   PetscFunctionBegin;
1633   ierr = PetscNewLog(p,DM_Composite,&com);CHKERRQ(ierr);
1634   p->data = com;
1635   ierr = PetscObjectChangeTypeName((PetscObject)p,"DMComposite");CHKERRQ(ierr);
1636   com->n            = 0;
1637   com->next         = PETSC_NULL;
1638   com->nredundant   = 0;
1639   com->nDM          = 0;
1640 
1641   p->ops->createglobalvector              = DMCreateGlobalVector_Composite;
1642   p->ops->createlocalvector               = DMCreateLocalVector_Composite;
1643   p->ops->createlocaltoglobalmapping      = DMCreateLocalToGlobalMapping_Composite;
1644   p->ops->createlocaltoglobalmappingblock = 0;
1645   p->ops->refine                          = DMRefine_Composite;
1646   p->ops->coarsen                         = DMCoarsen_Composite;
1647   p->ops->getinterpolation                = DMGetInterpolation_Composite;
1648   p->ops->getmatrix                       = DMGetMatrix_Composite;
1649   p->ops->getcoloring                     = DMGetColoring_Composite;
1650   p->ops->globaltolocalbegin              = DMGlobalToLocalBegin_Composite;
1651   p->ops->globaltolocalend                = DMGlobalToLocalEnd_Composite;
1652   p->ops->destroy                         = DMDestroy_Composite;
1653   p->ops->view                            = DMView_Composite;
1654   p->ops->setup                           = DMSetUp_Composite;
1655   PetscFunctionReturn(0);
1656 }
1657 EXTERN_C_END
1658 
1659 #undef __FUNCT__
1660 #define __FUNCT__ "DMCompositeCreate"
1661 /*@C
1662     DMCompositeCreate - Creates a vector packer, used to generate "composite"
1663       vectors made up of several subvectors.
1664 
1665     Collective on MPI_Comm
1666 
1667     Input Parameter:
1668 .   comm - the processors that will share the global vector
1669 
1670     Output Parameters:
1671 .   packer - the packer object
1672 
1673     Level: advanced
1674 
1675 .seealso DMDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeScatter(),
1676          DMCompositeGather(), DMCreateGlobalVector(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess()
1677          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
1678 
1679 @*/
1680 PetscErrorCode  DMCompositeCreate(MPI_Comm comm,DM *packer)
1681 {
1682   PetscErrorCode ierr;
1683 
1684   PetscFunctionBegin;
1685   PetscValidPointer(packer,2);
1686   ierr = DMCreate(comm,packer);CHKERRQ(ierr);
1687   ierr = DMSetType(*packer,DMCOMPOSITE);CHKERRQ(ierr);
1688   PetscFunctionReturn(0);
1689 }
1690