xref: /petsc/src/dm/impls/composite/pack.c (revision 487a658c8b32ba712a1dc8280daad2fd70c1dcd9)
1 
2 #include <../src/dm/impls/composite/packimpl.h>       /*I  "petscdmcomposite.h"  I*/
3 #include <petsc/private/isimpl.h>
4 #include <petsc/private/glvisviewerimpl.h>
5 #include <petscds.h>
6 
7 /*@C
8     DMCompositeSetCoupling - Sets user provided routines that compute the coupling between the
9       separate components (DMs) in a DMto build the correct matrix nonzero structure.
10 
11 
12     Logically Collective on MPI_Comm
13 
14     Input Parameter:
15 +   dm - the composite object
16 -   formcouplelocations - routine to set the nonzero locations in the matrix
17 
18     Level: advanced
19 
20     Not available from Fortran
21 
22     Notes:
23     See DMSetApplicationContext() and DMGetApplicationContext() for how to get user information into
24         this routine
25 
26 @*/
27 PetscErrorCode  DMCompositeSetCoupling(DM dm,PetscErrorCode (*FormCoupleLocations)(DM,Mat,PetscInt*,PetscInt*,PetscInt,PetscInt,PetscInt,PetscInt))
28 {
29   DM_Composite   *com = (DM_Composite*)dm->data;
30   PetscBool      flg;
31   PetscErrorCode ierr;
32 
33   PetscFunctionBegin;
34   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
35   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
36   com->FormCoupleLocations = FormCoupleLocations;
37   PetscFunctionReturn(0);
38 }
39 
40 PetscErrorCode  DMDestroy_Composite(DM dm)
41 {
42   PetscErrorCode         ierr;
43   struct DMCompositeLink *next, *prev;
44   DM_Composite           *com = (DM_Composite*)dm->data;
45 
46   PetscFunctionBegin;
47   next = com->next;
48   while (next) {
49     prev = next;
50     next = next->next;
51     ierr = DMDestroy(&prev->dm);CHKERRQ(ierr);
52     ierr = PetscFree(prev->grstarts);CHKERRQ(ierr);
53     ierr = PetscFree(prev);CHKERRQ(ierr);
54   }
55   ierr = PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL);CHKERRQ(ierr);
56   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
57   ierr = PetscFree(com);CHKERRQ(ierr);
58   PetscFunctionReturn(0);
59 }
60 
61 PetscErrorCode  DMView_Composite(DM dm,PetscViewer v)
62 {
63   PetscErrorCode ierr;
64   PetscBool      iascii;
65   DM_Composite   *com = (DM_Composite*)dm->data;
66 
67   PetscFunctionBegin;
68   ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
69   if (iascii) {
70     struct DMCompositeLink *lnk = com->next;
71     PetscInt               i;
72 
73     ierr = PetscViewerASCIIPrintf(v,"DM (%s)\n",((PetscObject)dm)->prefix ? ((PetscObject)dm)->prefix : "no prefix");CHKERRQ(ierr);
74     ierr = PetscViewerASCIIPrintf(v,"  contains %D DMs\n",com->nDM);CHKERRQ(ierr);
75     ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr);
76     for (i=0; lnk; lnk=lnk->next,i++) {
77       ierr = PetscViewerASCIIPrintf(v,"Link %D: DM of type %s\n",i,((PetscObject)lnk->dm)->type_name);CHKERRQ(ierr);
78       ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr);
79       ierr = DMView(lnk->dm,v);CHKERRQ(ierr);
80       ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr);
81     }
82     ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr);
83   }
84   PetscFunctionReturn(0);
85 }
86 
87 /* --------------------------------------------------------------------------------------*/
88 PetscErrorCode  DMSetUp_Composite(DM dm)
89 {
90   PetscErrorCode         ierr;
91   PetscInt               nprev = 0;
92   PetscMPIInt            rank,size;
93   DM_Composite           *com  = (DM_Composite*)dm->data;
94   struct DMCompositeLink *next = com->next;
95   PetscLayout            map;
96 
97   PetscFunctionBegin;
98   if (com->setup) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Packer has already been setup");
99   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)dm),&map);CHKERRQ(ierr);
100   ierr = PetscLayoutSetLocalSize(map,com->n);CHKERRQ(ierr);
101   ierr = PetscLayoutSetSize(map,PETSC_DETERMINE);CHKERRQ(ierr);
102   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
103   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
104   ierr = PetscLayoutGetSize(map,&com->N);CHKERRQ(ierr);
105   ierr = PetscLayoutGetRange(map,&com->rstart,NULL);CHKERRQ(ierr);
106   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
107 
108   /* now set the rstart for each linked vector */
109   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
110   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm),&size);CHKERRQ(ierr);
111   while (next) {
112     next->rstart  = nprev;
113     nprev        += next->n;
114     next->grstart = com->rstart + next->rstart;
115     ierr          = PetscMalloc1(size,&next->grstarts);CHKERRQ(ierr);
116     ierr          = MPI_Allgather(&next->grstart,1,MPIU_INT,next->grstarts,1,MPIU_INT,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
117     next          = next->next;
118   }
119   com->setup = PETSC_TRUE;
120   PetscFunctionReturn(0);
121 }
122 
123 /* ----------------------------------------------------------------------------------*/
124 
125 /*@
126     DMCompositeGetNumberDM - Get's the number of DM objects in the DMComposite
127        representation.
128 
129     Not Collective
130 
131     Input Parameter:
132 .    dm - the packer object
133 
134     Output Parameter:
135 .     nDM - the number of DMs
136 
137     Level: beginner
138 
139 @*/
140 PetscErrorCode  DMCompositeGetNumberDM(DM dm,PetscInt *nDM)
141 {
142   DM_Composite   *com = (DM_Composite*)dm->data;
143   PetscBool      flg;
144   PetscErrorCode ierr;
145 
146   PetscFunctionBegin;
147   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
148   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
149   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
150   *nDM = com->nDM;
151   PetscFunctionReturn(0);
152 }
153 
154 
155 /*@C
156     DMCompositeGetAccess - Allows one to access the individual packed vectors in their global
157        representation.
158 
159     Collective on DMComposite
160 
161     Input Parameters:
162 +    dm - the packer object
163 -    gvec - the global vector
164 
165     Output Parameters:
166 .    Vec* ... - the packed parallel vectors, NULL for those that are not needed
167 
168     Notes:
169     Use DMCompositeRestoreAccess() to return the vectors when you no longer need them
170 
171     Fortran Notes:
172 
173     Fortran callers must use numbered versions of this routine, e.g., DMCompositeGetAccess4(dm,gvec,vec1,vec2,vec3,vec4)
174     or use the alternative interface DMCompositeGetAccessArray().
175 
176     Level: advanced
177 
178 .seealso: DMCompositeGetEntries(), DMCompositeScatter()
179 @*/
180 PetscErrorCode  DMCompositeGetAccess(DM dm,Vec gvec,...)
181 {
182   va_list                Argp;
183   PetscErrorCode         ierr;
184   struct DMCompositeLink *next;
185   DM_Composite           *com = (DM_Composite*)dm->data;
186   PetscInt               readonly;
187   PetscBool              flg;
188 
189   PetscFunctionBegin;
190   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
191   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
192   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
193   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
194   next = com->next;
195   if (!com->setup) {
196     ierr = DMSetUp(dm);CHKERRQ(ierr);
197   }
198 
199   ierr = VecLockGet(gvec,&readonly);CHKERRQ(ierr);
200   /* loop over packed objects, handling one at at time */
201   va_start(Argp,gvec);
202   while (next) {
203     Vec *vec;
204     vec = va_arg(Argp, Vec*);
205     if (vec) {
206       ierr = DMGetGlobalVector(next->dm,vec);CHKERRQ(ierr);
207       if (readonly) {
208         const PetscScalar *array;
209         ierr = VecGetArrayRead(gvec,&array);CHKERRQ(ierr);
210         ierr = VecPlaceArray(*vec,array+next->rstart);CHKERRQ(ierr);
211         ierr = VecLockPush(*vec);CHKERRQ(ierr);
212         ierr = VecRestoreArrayRead(gvec,&array);CHKERRQ(ierr);
213       } else {
214         PetscScalar *array;
215         ierr = VecGetArray(gvec,&array);CHKERRQ(ierr);
216         ierr = VecPlaceArray(*vec,array+next->rstart);CHKERRQ(ierr);
217         ierr = VecRestoreArray(gvec,&array);CHKERRQ(ierr);
218       }
219     }
220     next = next->next;
221   }
222   va_end(Argp);
223   PetscFunctionReturn(0);
224 }
225 
226 /*@C
227     DMCompositeGetAccessArray - Allows one to access the individual packed vectors in their global
228        representation.
229 
230     Collective on DMComposite
231 
232     Input Parameters:
233 +    dm - the packer object
234 .    pvec - packed vector
235 .    nwanted - number of vectors wanted
236 -    wanted - sorted array of vectors wanted, or NULL to get all vectors
237 
238     Output Parameters:
239 .    vecs - array of requested global vectors (must be allocated)
240 
241     Notes:
242     Use DMCompositeRestoreAccessArray() to return the vectors when you no longer need them
243 
244     Level: advanced
245 
246 .seealso: DMCompositeGetAccess(), DMCompositeGetEntries(), DMCompositeScatter(), DMCompositeGather()
247 @*/
248 PetscErrorCode  DMCompositeGetAccessArray(DM dm,Vec pvec,PetscInt nwanted,const PetscInt *wanted,Vec *vecs)
249 {
250   PetscErrorCode         ierr;
251   struct DMCompositeLink *link;
252   PetscInt               i,wnum;
253   DM_Composite           *com = (DM_Composite*)dm->data;
254   PetscInt               readonly;
255   PetscBool              flg;
256 
257   PetscFunctionBegin;
258   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
259   PetscValidHeaderSpecific(pvec,VEC_CLASSID,2);
260   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
261   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
262   if (!com->setup) {
263     ierr = DMSetUp(dm);CHKERRQ(ierr);
264   }
265 
266   ierr = VecLockGet(pvec,&readonly);CHKERRQ(ierr);
267   for (i=0,wnum=0,link=com->next; link && wnum<nwanted; i++,link=link->next) {
268     if (!wanted || i == wanted[wnum]) {
269       Vec v;
270       ierr = DMGetGlobalVector(link->dm,&v);CHKERRQ(ierr);
271       if (readonly) {
272         const PetscScalar *array;
273         ierr = VecGetArrayRead(pvec,&array);CHKERRQ(ierr);
274         ierr = VecPlaceArray(v,array+link->rstart);CHKERRQ(ierr);
275         ierr = VecLockPush(v);CHKERRQ(ierr);
276         ierr = VecRestoreArrayRead(pvec,&array);CHKERRQ(ierr);
277       } else {
278         PetscScalar *array;
279         ierr = VecGetArray(pvec,&array);CHKERRQ(ierr);
280         ierr = VecPlaceArray(v,array+link->rstart);CHKERRQ(ierr);
281         ierr = VecRestoreArray(pvec,&array);CHKERRQ(ierr);
282       }
283       vecs[wnum++] = v;
284     }
285   }
286   PetscFunctionReturn(0);
287 }
288 
289 /*@C
290     DMCompositeGetLocalAccessArray - Allows one to access the individual
291     packed vectors in their local representation.
292 
293     Collective on DMComposite.
294 
295     Input Parameters:
296 +    dm - the packer object
297 .    pvec - packed vector
298 .    nwanted - number of vectors wanted
299 -    wanted - sorted array of vectors wanted, or NULL to get all vectors
300 
301     Output Parameters:
302 .    vecs - array of requested local vectors (must be allocated)
303 
304     Notes:
305     Use DMCompositeRestoreLocalAccessArray() to return the vectors
306     when you no longer need them.
307 
308     Level: advanced
309 
310 .seealso: DMCompositeRestoreLocalAccessArray(), DMCompositeGetAccess(),
311 DMCompositeGetEntries(), DMCompositeScatter(), DMCompositeGather()
312 @*/
313 PetscErrorCode  DMCompositeGetLocalAccessArray(DM dm,Vec pvec,PetscInt nwanted,const PetscInt *wanted,Vec *vecs)
314 {
315   PetscErrorCode         ierr;
316   struct DMCompositeLink *link;
317   PetscInt               i,wnum;
318   DM_Composite           *com = (DM_Composite*)dm->data;
319   PetscInt               readonly;
320   PetscInt               nlocal = 0;
321   PetscBool              flg;
322 
323   PetscFunctionBegin;
324   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
325   PetscValidHeaderSpecific(pvec,VEC_CLASSID,2);
326   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
327   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
328   if (!com->setup) {
329     ierr = DMSetUp(dm);CHKERRQ(ierr);
330   }
331 
332   ierr = VecLockGet(pvec,&readonly);CHKERRQ(ierr);
333   for (i=0,wnum=0,link=com->next; link && wnum<nwanted; i++,link=link->next) {
334     if (!wanted || i == wanted[wnum]) {
335       Vec v;
336       ierr = DMGetLocalVector(link->dm,&v);CHKERRQ(ierr);
337       if (readonly) {
338         const PetscScalar *array;
339         ierr = VecGetArrayRead(pvec,&array);CHKERRQ(ierr);
340         ierr = VecPlaceArray(v,array+nlocal);CHKERRQ(ierr);
341         ierr = VecLockPush(v);CHKERRQ(ierr);
342         ierr = VecRestoreArrayRead(pvec,&array);CHKERRQ(ierr);
343       } else {
344         PetscScalar *array;
345         ierr = VecGetArray(pvec,&array);CHKERRQ(ierr);
346         ierr = VecPlaceArray(v,array+nlocal);CHKERRQ(ierr);
347         ierr = VecRestoreArray(pvec,&array);CHKERRQ(ierr);
348       }
349       vecs[wnum++] = v;
350     }
351 
352     nlocal += link->nlocal;
353   }
354 
355   PetscFunctionReturn(0);
356 }
357 
358 /*@C
359     DMCompositeRestoreAccess - Returns the vectors obtained with DMCompositeGetAccess()
360        representation.
361 
362     Collective on DMComposite
363 
364     Input Parameters:
365 +    dm - the packer object
366 .    gvec - the global vector
367 -    Vec* ... - the individual parallel vectors, NULL for those that are not needed
368 
369     Level: advanced
370 
371 .seealso  DMCompositeAddDM(), DMCreateGlobalVector(),
372          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeScatter(),
373          DMCompositeRestoreAccess(), DMCompositeGetAccess()
374 
375 @*/
376 PetscErrorCode  DMCompositeRestoreAccess(DM dm,Vec gvec,...)
377 {
378   va_list                Argp;
379   PetscErrorCode         ierr;
380   struct DMCompositeLink *next;
381   DM_Composite           *com = (DM_Composite*)dm->data;
382   PetscInt               readonly;
383   PetscBool              flg;
384 
385   PetscFunctionBegin;
386   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
387   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
388   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
389   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
390   next = com->next;
391   if (!com->setup) {
392     ierr = DMSetUp(dm);CHKERRQ(ierr);
393   }
394 
395   ierr = VecLockGet(gvec,&readonly);CHKERRQ(ierr);
396   /* loop over packed objects, handling one at at time */
397   va_start(Argp,gvec);
398   while (next) {
399     Vec *vec;
400     vec = va_arg(Argp, Vec*);
401     if (vec) {
402       ierr = VecResetArray(*vec);CHKERRQ(ierr);
403       if (readonly) {
404         ierr = VecLockPop(*vec);CHKERRQ(ierr);
405       }
406       ierr = DMRestoreGlobalVector(next->dm,vec);CHKERRQ(ierr);
407     }
408     next = next->next;
409   }
410   va_end(Argp);
411   PetscFunctionReturn(0);
412 }
413 
414 /*@C
415     DMCompositeRestoreAccessArray - Returns the vectors obtained with DMCompositeGetAccessArray()
416 
417     Collective on DMComposite
418 
419     Input Parameters:
420 +    dm - the packer object
421 .    pvec - packed vector
422 .    nwanted - number of vectors wanted
423 .    wanted - sorted array of vectors wanted, or NULL to get all vectors
424 -    vecs - array of global vectors to return
425 
426     Level: advanced
427 
428 .seealso: DMCompositeRestoreAccess(), DMCompositeRestoreEntries(), DMCompositeScatter(), DMCompositeGather()
429 @*/
430 PetscErrorCode  DMCompositeRestoreAccessArray(DM dm,Vec pvec,PetscInt nwanted,const PetscInt *wanted,Vec *vecs)
431 {
432   PetscErrorCode         ierr;
433   struct DMCompositeLink *link;
434   PetscInt               i,wnum;
435   DM_Composite           *com = (DM_Composite*)dm->data;
436   PetscInt               readonly;
437   PetscBool              flg;
438 
439   PetscFunctionBegin;
440   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
441   PetscValidHeaderSpecific(pvec,VEC_CLASSID,2);
442   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
443   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
444   if (!com->setup) {
445     ierr = DMSetUp(dm);CHKERRQ(ierr);
446   }
447 
448   ierr = VecLockGet(pvec,&readonly);CHKERRQ(ierr);
449   for (i=0,wnum=0,link=com->next; link && wnum<nwanted; i++,link=link->next) {
450     if (!wanted || i == wanted[wnum]) {
451       ierr = VecResetArray(vecs[wnum]);CHKERRQ(ierr);
452       if (readonly) {
453         ierr = VecLockPop(vecs[wnum]);CHKERRQ(ierr);
454       }
455       ierr = DMRestoreGlobalVector(link->dm,&vecs[wnum]);CHKERRQ(ierr);
456       wnum++;
457     }
458   }
459   PetscFunctionReturn(0);
460 }
461 
462 /*@C
463     DMCompositeRestoreLocalAccessArray - Returns the vectors obtained with DMCompositeGetLocalAccessArray().
464 
465     Collective on DMComposite.
466 
467     Input Parameters:
468 +    dm - the packer object
469 .    pvec - packed vector
470 .    nwanted - number of vectors wanted
471 .    wanted - sorted array of vectors wanted, or NULL to restore all vectors
472 -    vecs - array of local vectors to return
473 
474     Level: advanced
475 
476     Notes:
477     nwanted and wanted must match the values given to DMCompositeGetLocalAccessArray()
478     otherwise the call will fail.
479 
480 .seealso: DMCompositeGetLocalAccessArray(), DMCompositeRestoreAccessArray(),
481 DMCompositeRestoreAccess(), DMCompositeRestoreEntries(),
482 DMCompositeScatter(), DMCompositeGather()
483 @*/
484 PetscErrorCode  DMCompositeRestoreLocalAccessArray(DM dm,Vec pvec,PetscInt nwanted,const PetscInt *wanted,Vec *vecs)
485 {
486   PetscErrorCode         ierr;
487   struct DMCompositeLink *link;
488   PetscInt               i,wnum;
489   DM_Composite           *com = (DM_Composite*)dm->data;
490   PetscInt               readonly;
491   PetscBool              flg;
492 
493   PetscFunctionBegin;
494   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
495   PetscValidHeaderSpecific(pvec,VEC_CLASSID,2);
496   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
497   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
498   if (!com->setup) {
499     ierr = DMSetUp(dm);CHKERRQ(ierr);
500   }
501 
502   ierr = VecLockGet(pvec,&readonly);CHKERRQ(ierr);
503   for (i=0,wnum=0,link=com->next; link && wnum<nwanted; i++,link=link->next) {
504     if (!wanted || i == wanted[wnum]) {
505       ierr = VecResetArray(vecs[wnum]);CHKERRQ(ierr);
506       if (readonly) {
507         ierr = VecLockPop(vecs[wnum]);CHKERRQ(ierr);
508       }
509       ierr = DMRestoreLocalVector(link->dm,&vecs[wnum]);CHKERRQ(ierr);
510       wnum++;
511     }
512   }
513   PetscFunctionReturn(0);
514 }
515 
516 /*@C
517     DMCompositeScatter - Scatters from a global packed vector into its individual local vectors
518 
519     Collective on DMComposite
520 
521     Input Parameters:
522 +    dm - the packer object
523 .    gvec - the global vector
524 -    Vec ... - the individual sequential vectors, NULL for those that are not needed
525 
526     Level: advanced
527 
528     Notes:
529     DMCompositeScatterArray() is a non-variadic alternative that is often more convenient for library callers and is
530     accessible from Fortran.
531 
532 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
533          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
534          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
535          DMCompositeScatterArray()
536 
537 @*/
538 PetscErrorCode  DMCompositeScatter(DM dm,Vec gvec,...)
539 {
540   va_list                Argp;
541   PetscErrorCode         ierr;
542   struct DMCompositeLink *next;
543   PetscInt               cnt;
544   DM_Composite           *com = (DM_Composite*)dm->data;
545   PetscBool              flg;
546 
547   PetscFunctionBegin;
548   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
549   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
550   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
551   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
552   if (!com->setup) {
553     ierr = DMSetUp(dm);CHKERRQ(ierr);
554   }
555 
556   /* loop over packed objects, handling one at at time */
557   va_start(Argp,gvec);
558   for (cnt=3,next=com->next; next; cnt++,next=next->next) {
559     Vec local;
560     local = va_arg(Argp, Vec);
561     if (local) {
562       Vec               global;
563       const PetscScalar *array;
564       PetscValidHeaderSpecific(local,VEC_CLASSID,cnt);
565       ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
566       ierr = VecGetArrayRead(gvec,&array);CHKERRQ(ierr);
567       ierr = VecPlaceArray(global,array+next->rstart);CHKERRQ(ierr);
568       ierr = DMGlobalToLocalBegin(next->dm,global,INSERT_VALUES,local);CHKERRQ(ierr);
569       ierr = DMGlobalToLocalEnd(next->dm,global,INSERT_VALUES,local);CHKERRQ(ierr);
570       ierr = VecRestoreArrayRead(gvec,&array);CHKERRQ(ierr);
571       ierr = VecResetArray(global);CHKERRQ(ierr);
572       ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
573     }
574   }
575   va_end(Argp);
576   PetscFunctionReturn(0);
577 }
578 
579 /*@
580     DMCompositeScatterArray - Scatters from a global packed vector into its individual local vectors
581 
582     Collective on DMComposite
583 
584     Input Parameters:
585 +    dm - the packer object
586 .    gvec - the global vector
587 .    lvecs - array of local vectors, NULL for any that are not needed
588 
589     Level: advanced
590 
591     Note:
592     This is a non-variadic alternative to DMCompositeScatter()
593 
594 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector()
595          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
596          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
597 
598 @*/
599 PetscErrorCode  DMCompositeScatterArray(DM dm,Vec gvec,Vec *lvecs)
600 {
601   PetscErrorCode         ierr;
602   struct DMCompositeLink *next;
603   PetscInt               i;
604   DM_Composite           *com = (DM_Composite*)dm->data;
605   PetscBool              flg;
606 
607   PetscFunctionBegin;
608   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
609   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
610   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
611   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
612   if (!com->setup) {
613     ierr = DMSetUp(dm);CHKERRQ(ierr);
614   }
615 
616   /* loop over packed objects, handling one at at time */
617   for (i=0,next=com->next; next; next=next->next,i++) {
618     if (lvecs[i]) {
619       Vec         global;
620       const PetscScalar *array;
621       PetscValidHeaderSpecific(lvecs[i],VEC_CLASSID,3);
622       ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
623       ierr = VecGetArrayRead(gvec,&array);CHKERRQ(ierr);
624       ierr = VecPlaceArray(global,(PetscScalar*)array+next->rstart);CHKERRQ(ierr);
625       ierr = DMGlobalToLocalBegin(next->dm,global,INSERT_VALUES,lvecs[i]);CHKERRQ(ierr);
626       ierr = DMGlobalToLocalEnd(next->dm,global,INSERT_VALUES,lvecs[i]);CHKERRQ(ierr);
627       ierr = VecRestoreArrayRead(gvec,&array);CHKERRQ(ierr);
628       ierr = VecResetArray(global);CHKERRQ(ierr);
629       ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
630     }
631   }
632   PetscFunctionReturn(0);
633 }
634 
635 /*@C
636     DMCompositeGather - Gathers into a global packed vector from its individual local vectors
637 
638     Collective on DMComposite
639 
640     Input Parameter:
641 +    dm - the packer object
642 .    gvec - the global vector
643 .    imode - INSERT_VALUES or ADD_VALUES
644 -    Vec ... - the individual sequential vectors, NULL for any that are not needed
645 
646     Level: advanced
647 
648     Not available from Fortran, Fortran users can use DMCompositeGatherArray()
649 
650 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
651          DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
652          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
653 
654 @*/
655 PetscErrorCode  DMCompositeGather(DM dm,InsertMode imode,Vec gvec,...)
656 {
657   va_list                Argp;
658   PetscErrorCode         ierr;
659   struct DMCompositeLink *next;
660   DM_Composite           *com = (DM_Composite*)dm->data;
661   PetscInt               cnt;
662   PetscBool              flg;
663 
664   PetscFunctionBegin;
665   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
666   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
667   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
668   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
669   if (!com->setup) {
670     ierr = DMSetUp(dm);CHKERRQ(ierr);
671   }
672 
673   /* loop over packed objects, handling one at at time */
674   va_start(Argp,gvec);
675   for (cnt=3,next=com->next; next; cnt++,next=next->next) {
676     Vec local;
677     local = va_arg(Argp, Vec);
678     if (local) {
679       PetscScalar *array;
680       Vec         global;
681       PetscValidHeaderSpecific(local,VEC_CLASSID,cnt);
682       ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
683       ierr = VecGetArray(gvec,&array);CHKERRQ(ierr);
684       ierr = VecPlaceArray(global,array+next->rstart);CHKERRQ(ierr);
685       ierr = DMLocalToGlobalBegin(next->dm,local,imode,global);CHKERRQ(ierr);
686       ierr = DMLocalToGlobalEnd(next->dm,local,imode,global);CHKERRQ(ierr);
687       ierr = VecRestoreArray(gvec,&array);CHKERRQ(ierr);
688       ierr = VecResetArray(global);CHKERRQ(ierr);
689       ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
690     }
691   }
692   va_end(Argp);
693   PetscFunctionReturn(0);
694 }
695 
696 /*@
697     DMCompositeGatherArray - Gathers into a global packed vector from its individual local vectors
698 
699     Collective on DMComposite
700 
701     Input Parameter:
702 +    dm - the packer object
703 .    gvec - the global vector
704 .    imode - INSERT_VALUES or ADD_VALUES
705 -    lvecs - the individual sequential vectors, NULL for any that are not needed
706 
707     Level: advanced
708 
709     Notes:
710     This is a non-variadic alternative to DMCompositeGather().
711 
712 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
713          DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
714          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries(),
715 @*/
716 PetscErrorCode  DMCompositeGatherArray(DM dm,InsertMode imode,Vec gvec,Vec *lvecs)
717 {
718   PetscErrorCode         ierr;
719   struct DMCompositeLink *next;
720   DM_Composite           *com = (DM_Composite*)dm->data;
721   PetscInt               i;
722   PetscBool              flg;
723 
724   PetscFunctionBegin;
725   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
726   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
727   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
728   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
729   if (!com->setup) {
730     ierr = DMSetUp(dm);CHKERRQ(ierr);
731   }
732 
733   /* loop over packed objects, handling one at at time */
734   for (next=com->next,i=0; next; next=next->next,i++) {
735     if (lvecs[i]) {
736       PetscScalar *array;
737       Vec         global;
738       PetscValidHeaderSpecific(lvecs[i],VEC_CLASSID,3);
739       ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
740       ierr = VecGetArray(gvec,&array);CHKERRQ(ierr);
741       ierr = VecPlaceArray(global,array+next->rstart);CHKERRQ(ierr);
742       ierr = DMLocalToGlobalBegin(next->dm,lvecs[i],imode,global);CHKERRQ(ierr);
743       ierr = DMLocalToGlobalEnd(next->dm,lvecs[i],imode,global);CHKERRQ(ierr);
744       ierr = VecRestoreArray(gvec,&array);CHKERRQ(ierr);
745       ierr = VecResetArray(global);CHKERRQ(ierr);
746       ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
747     }
748   }
749   PetscFunctionReturn(0);
750 }
751 
752 /*@
753     DMCompositeAddDM - adds a DM vector to a DMComposite
754 
755     Collective on DMComposite
756 
757     Input Parameter:
758 +    dmc - the DMComposite (packer) object
759 -    dm - the DM object
760 
761     Level: advanced
762 
763 .seealso DMDestroy(), DMCompositeGather(), DMCompositeAddDM(), DMCreateGlobalVector(),
764          DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
765          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
766 
767 @*/
768 PetscErrorCode  DMCompositeAddDM(DM dmc,DM dm)
769 {
770   PetscErrorCode         ierr;
771   PetscInt               n,nlocal;
772   struct DMCompositeLink *mine,*next;
773   Vec                    global,local;
774   DM_Composite           *com = (DM_Composite*)dmc->data;
775   PetscBool              flg;
776 
777   PetscFunctionBegin;
778   PetscValidHeaderSpecific(dmc,DM_CLASSID,1);
779   PetscValidHeaderSpecific(dm,DM_CLASSID,2);
780   ierr = PetscObjectTypeCompare((PetscObject)dmc,DMCOMPOSITE,&flg);CHKERRQ(ierr);
781   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
782   next = com->next;
783   if (com->setup) SETERRQ(PetscObjectComm((PetscObject)dmc),PETSC_ERR_ARG_WRONGSTATE,"Cannot add a DM once you have used the DMComposite");
784 
785   /* create new link */
786   ierr = PetscNew(&mine);CHKERRQ(ierr);
787   ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
788   ierr = DMGetGlobalVector(dm,&global);CHKERRQ(ierr);
789   ierr = VecGetLocalSize(global,&n);CHKERRQ(ierr);
790   ierr = DMRestoreGlobalVector(dm,&global);CHKERRQ(ierr);
791   ierr = DMGetLocalVector(dm,&local);CHKERRQ(ierr);
792   ierr = VecGetSize(local,&nlocal);CHKERRQ(ierr);
793   ierr = DMRestoreLocalVector(dm,&local);CHKERRQ(ierr);
794 
795   mine->n      = n;
796   mine->nlocal = nlocal;
797   mine->dm     = dm;
798   mine->next   = NULL;
799   com->n      += n;
800   com->nghost += nlocal;
801 
802   /* add to end of list */
803   if (!next) com->next = mine;
804   else {
805     while (next->next) next = next->next;
806     next->next = mine;
807   }
808   com->nDM++;
809   com->nmine++;
810   PetscFunctionReturn(0);
811 }
812 
813 #include <petscdraw.h>
814 PETSC_EXTERN PetscErrorCode  VecView_MPI(Vec,PetscViewer);
815 PetscErrorCode  VecView_DMComposite(Vec gvec,PetscViewer viewer)
816 {
817   DM                     dm;
818   PetscErrorCode         ierr;
819   struct DMCompositeLink *next;
820   PetscBool              isdraw;
821   DM_Composite           *com;
822 
823   PetscFunctionBegin;
824   ierr = VecGetDM(gvec, &dm);CHKERRQ(ierr);
825   if (!dm) SETERRQ(PetscObjectComm((PetscObject)gvec),PETSC_ERR_ARG_WRONG,"Vector not generated from a DMComposite");
826   com  = (DM_Composite*)dm->data;
827   next = com->next;
828 
829   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
830   if (!isdraw) {
831     /* do I really want to call this? */
832     ierr = VecView_MPI(gvec,viewer);CHKERRQ(ierr);
833   } else {
834     PetscInt cnt = 0;
835 
836     /* loop over packed objects, handling one at at time */
837     while (next) {
838       Vec               vec;
839       const PetscScalar *array;
840       PetscInt          bs;
841 
842       /* Should use VecGetSubVector() eventually, but would need to forward the DM for that to work */
843       ierr = DMGetGlobalVector(next->dm,&vec);CHKERRQ(ierr);
844       ierr = VecGetArrayRead(gvec,&array);CHKERRQ(ierr);
845       ierr = VecPlaceArray(vec,(PetscScalar*)array+next->rstart);CHKERRQ(ierr);
846       ierr = VecRestoreArrayRead(gvec,&array);CHKERRQ(ierr);
847       ierr = VecView(vec,viewer);CHKERRQ(ierr);
848       ierr = VecResetArray(vec);CHKERRQ(ierr);
849       ierr = VecGetBlockSize(vec,&bs);CHKERRQ(ierr);
850       ierr = DMRestoreGlobalVector(next->dm,&vec);CHKERRQ(ierr);
851       ierr = PetscViewerDrawBaseAdd(viewer,bs);CHKERRQ(ierr);
852       cnt += bs;
853       next = next->next;
854     }
855     ierr = PetscViewerDrawBaseAdd(viewer,-cnt);CHKERRQ(ierr);
856   }
857   PetscFunctionReturn(0);
858 }
859 
860 PetscErrorCode  DMCreateGlobalVector_Composite(DM dm,Vec *gvec)
861 {
862   PetscErrorCode ierr;
863   DM_Composite   *com = (DM_Composite*)dm->data;
864 
865   PetscFunctionBegin;
866   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
867   ierr = DMSetUp(dm);CHKERRQ(ierr);
868   ierr = VecCreateMPI(PetscObjectComm((PetscObject)dm),com->n,com->N,gvec);CHKERRQ(ierr);
869   ierr = VecSetDM(*gvec, dm);CHKERRQ(ierr);
870   ierr = VecSetOperation(*gvec,VECOP_VIEW,(void (*)(void))VecView_DMComposite);CHKERRQ(ierr);
871   PetscFunctionReturn(0);
872 }
873 
874 PetscErrorCode  DMCreateLocalVector_Composite(DM dm,Vec *lvec)
875 {
876   PetscErrorCode ierr;
877   DM_Composite   *com = (DM_Composite*)dm->data;
878 
879   PetscFunctionBegin;
880   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
881   if (!com->setup) {
882     ierr = DMSetUp(dm);CHKERRQ(ierr);
883   }
884   ierr = VecCreateSeq(PETSC_COMM_SELF,com->nghost,lvec);CHKERRQ(ierr);
885   ierr = VecSetDM(*lvec, dm);CHKERRQ(ierr);
886   PetscFunctionReturn(0);
887 }
888 
889 /*@C
890     DMCompositeGetISLocalToGlobalMappings - gets an ISLocalToGlobalMapping for each DM in the DMComposite, maps to the composite global space
891 
892     Collective on DM
893 
894     Input Parameter:
895 .    dm - the packer object
896 
897     Output Parameters:
898 .    ltogs - the individual mappings for each packed vector. Note that this includes
899            all the ghost points that individual ghosted DMDA's may have.
900 
901     Level: advanced
902 
903     Notes:
904        Each entry of ltogs should be destroyed with ISLocalToGlobalMappingDestroy(), the ltogs array should be freed with PetscFree().
905 
906     Not available from Fortran
907 
908 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
909          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetAccess(), DMCompositeScatter(),
910          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(),DMCompositeGetEntries()
911 
912 @*/
913 PetscErrorCode  DMCompositeGetISLocalToGlobalMappings(DM dm,ISLocalToGlobalMapping **ltogs)
914 {
915   PetscErrorCode         ierr;
916   PetscInt               i,*idx,n,cnt;
917   struct DMCompositeLink *next;
918   PetscMPIInt            rank;
919   DM_Composite           *com = (DM_Composite*)dm->data;
920   PetscBool              flg;
921 
922   PetscFunctionBegin;
923   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
924   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
925   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
926   ierr = DMSetUp(dm);CHKERRQ(ierr);
927   ierr = PetscMalloc1(com->nDM,ltogs);CHKERRQ(ierr);
928   next = com->next;
929   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
930 
931   /* loop over packed objects, handling one at at time */
932   cnt = 0;
933   while (next) {
934     ISLocalToGlobalMapping ltog;
935     PetscMPIInt            size;
936     const PetscInt         *suboff,*indices;
937     Vec                    global;
938 
939     /* Get sub-DM global indices for each local dof */
940     ierr = DMGetLocalToGlobalMapping(next->dm,&ltog);CHKERRQ(ierr);
941     ierr = ISLocalToGlobalMappingGetSize(ltog,&n);CHKERRQ(ierr);
942     ierr = ISLocalToGlobalMappingGetIndices(ltog,&indices);CHKERRQ(ierr);
943     ierr = PetscMalloc1(n,&idx);CHKERRQ(ierr);
944 
945     /* Get the offsets for the sub-DM global vector */
946     ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
947     ierr = VecGetOwnershipRanges(global,&suboff);CHKERRQ(ierr);
948     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)global),&size);CHKERRQ(ierr);
949 
950     /* Shift the sub-DM definition of the global space to the composite global space */
951     for (i=0; i<n; i++) {
952       PetscInt subi = indices[i],lo = 0,hi = size,t;
953       /* Binary search to find which rank owns subi */
954       while (hi-lo > 1) {
955         t = lo + (hi-lo)/2;
956         if (suboff[t] > subi) hi = t;
957         else                  lo = t;
958       }
959       idx[i] = subi - suboff[lo] + next->grstarts[lo];
960     }
961     ierr = ISLocalToGlobalMappingRestoreIndices(ltog,&indices);CHKERRQ(ierr);
962     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm),1,n,idx,PETSC_OWN_POINTER,&(*ltogs)[cnt]);CHKERRQ(ierr);
963     ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
964     next = next->next;
965     cnt++;
966   }
967   PetscFunctionReturn(0);
968 }
969 
970 /*@C
971    DMCompositeGetLocalISs - Gets index sets for each component of a composite local vector
972 
973    Not Collective
974 
975    Input Arguments:
976 . dm - composite DM
977 
978    Output Arguments:
979 . is - array of serial index sets for each each component of the DMComposite
980 
981    Level: intermediate
982 
983    Notes:
984    At present, a composite local vector does not normally exist.  This function is used to provide index sets for
985    MatGetLocalSubMatrix().  In the future, the scatters for each entry in the DMComposite may be be merged into a single
986    scatter to a composite local vector.  The user should not typically need to know which is being done.
987 
988    To get the composite global indices at all local points (including ghosts), use DMCompositeGetISLocalToGlobalMappings().
989 
990    To get index sets for pieces of the composite global vector, use DMCompositeGetGlobalISs().
991 
992    Each returned IS should be destroyed with ISDestroy(), the array should be freed with PetscFree().
993 
994    Not available from Fortran
995 
996 .seealso: DMCompositeGetGlobalISs(), DMCompositeGetISLocalToGlobalMappings(), MatGetLocalSubMatrix(), MatCreateLocalRef()
997 @*/
998 PetscErrorCode  DMCompositeGetLocalISs(DM dm,IS **is)
999 {
1000   PetscErrorCode         ierr;
1001   DM_Composite           *com = (DM_Composite*)dm->data;
1002   struct DMCompositeLink *link;
1003   PetscInt               cnt,start;
1004   PetscBool              flg;
1005 
1006   PetscFunctionBegin;
1007   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1008   PetscValidPointer(is,2);
1009   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
1010   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
1011   ierr = PetscMalloc1(com->nmine,is);CHKERRQ(ierr);
1012   for (cnt=0,start=0,link=com->next; link; start+=link->nlocal,cnt++,link=link->next) {
1013     PetscInt bs;
1014     ierr = ISCreateStride(PETSC_COMM_SELF,link->nlocal,start,1,&(*is)[cnt]);CHKERRQ(ierr);
1015     ierr = DMGetBlockSize(link->dm,&bs);CHKERRQ(ierr);
1016     ierr = ISSetBlockSize((*is)[cnt],bs);CHKERRQ(ierr);
1017   }
1018   PetscFunctionReturn(0);
1019 }
1020 
1021 /*@C
1022     DMCompositeGetGlobalISs - Gets the index sets for each composed object
1023 
1024     Collective on DMComposite
1025 
1026     Input Parameter:
1027 .    dm - the packer object
1028 
1029     Output Parameters:
1030 .    is - the array of index sets
1031 
1032     Level: advanced
1033 
1034     Notes:
1035        The is entries should be destroyed with ISDestroy(), the is array should be freed with PetscFree()
1036 
1037        These could be used to extract a subset of vector entries for a "multi-physics" preconditioner
1038 
1039        Use DMCompositeGetLocalISs() for index sets in the packed local numbering, and
1040        DMCompositeGetISLocalToGlobalMappings() for to map local sub-DM (including ghost) indices to packed global
1041        indices.
1042 
1043     Fortran Notes:
1044 
1045        The output argument 'is' must be an allocated array of sufficient length, which can be learned using DMCompositeGetNumberDM().
1046 
1047 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
1048          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetAccess(), DMCompositeScatter(),
1049          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(),DMCompositeGetEntries()
1050 
1051 @*/
1052 PetscErrorCode  DMCompositeGetGlobalISs(DM dm,IS *is[])
1053 {
1054   PetscErrorCode         ierr;
1055   PetscInt               cnt = 0;
1056   struct DMCompositeLink *next;
1057   PetscMPIInt            rank;
1058   DM_Composite           *com = (DM_Composite*)dm->data;
1059   PetscBool              flg;
1060 
1061   PetscFunctionBegin;
1062   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1063   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
1064   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
1065   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() before");
1066   ierr = PetscMalloc1(com->nDM,is);CHKERRQ(ierr);
1067   next = com->next;
1068   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
1069 
1070   /* loop over packed objects, handling one at at time */
1071   while (next) {
1072     ierr = ISCreateStride(PetscObjectComm((PetscObject)dm),next->n,next->grstart,1,&(*is)[cnt]);CHKERRQ(ierr);
1073     if (dm->prob) {
1074       MatNullSpace space;
1075       Mat          pmat;
1076       PetscObject  disc;
1077       PetscInt     Nf;
1078 
1079       ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr);
1080       if (cnt < Nf) {
1081         ierr = PetscDSGetDiscretization(dm->prob, cnt, &disc);CHKERRQ(ierr);
1082         ierr = PetscObjectQuery(disc, "nullspace", (PetscObject*) &space);CHKERRQ(ierr);
1083         if (space) {ierr = PetscObjectCompose((PetscObject) (*is)[cnt], "nullspace", (PetscObject) space);CHKERRQ(ierr);}
1084         ierr = PetscObjectQuery(disc, "nearnullspace", (PetscObject*) &space);CHKERRQ(ierr);
1085         if (space) {ierr = PetscObjectCompose((PetscObject) (*is)[cnt], "nearnullspace", (PetscObject) space);CHKERRQ(ierr);}
1086         ierr = PetscObjectQuery(disc, "pmat", (PetscObject*) &pmat);CHKERRQ(ierr);
1087         if (pmat) {ierr = PetscObjectCompose((PetscObject) (*is)[cnt], "pmat", (PetscObject) pmat);CHKERRQ(ierr);}
1088       }
1089     }
1090     cnt++;
1091     next = next->next;
1092   }
1093   PetscFunctionReturn(0);
1094 }
1095 
1096 PetscErrorCode DMCreateFieldIS_Composite(DM dm, PetscInt *numFields,char ***fieldNames, IS **fields)
1097 {
1098   PetscInt       nDM;
1099   DM             *dms;
1100   PetscInt       i;
1101   PetscErrorCode ierr;
1102 
1103   PetscFunctionBegin;
1104   ierr = DMCompositeGetNumberDM(dm, &nDM);CHKERRQ(ierr);
1105   if (numFields) *numFields = nDM;
1106   ierr = DMCompositeGetGlobalISs(dm, fields);CHKERRQ(ierr);
1107   if (fieldNames) {
1108     ierr = PetscMalloc1(nDM, &dms);CHKERRQ(ierr);
1109     ierr = PetscMalloc1(nDM, fieldNames);CHKERRQ(ierr);
1110     ierr = DMCompositeGetEntriesArray(dm, dms);CHKERRQ(ierr);
1111     for (i=0; i<nDM; i++) {
1112       char       buf[256];
1113       const char *splitname;
1114 
1115       /* Split naming precedence: object name, prefix, number */
1116       splitname = ((PetscObject) dm)->name;
1117       if (!splitname) {
1118         ierr = PetscObjectGetOptionsPrefix((PetscObject)dms[i],&splitname);CHKERRQ(ierr);
1119         if (splitname) {
1120           size_t len;
1121           ierr                 = PetscStrncpy(buf,splitname,sizeof(buf));CHKERRQ(ierr);
1122           buf[sizeof(buf) - 1] = 0;
1123           ierr                 = PetscStrlen(buf,&len);CHKERRQ(ierr);
1124           if (buf[len-1] == '_') buf[len-1] = 0; /* Remove trailing underscore if it was used */
1125           splitname = buf;
1126         }
1127       }
1128       if (!splitname) {
1129         ierr      = PetscSNPrintf(buf,sizeof(buf),"%D",i);CHKERRQ(ierr);
1130         splitname = buf;
1131       }
1132       ierr = PetscStrallocpy(splitname,&(*fieldNames)[i]);CHKERRQ(ierr);
1133     }
1134     ierr = PetscFree(dms);CHKERRQ(ierr);
1135   }
1136   PetscFunctionReturn(0);
1137 }
1138 
1139 /*
1140  This could take over from DMCreateFieldIS(), as it is more general,
1141  making DMCreateFieldIS() a special case -- calling with dmlist == NULL;
1142  At this point it's probably best to be less intrusive, however.
1143  */
1144 PetscErrorCode DMCreateFieldDecomposition_Composite(DM dm, PetscInt *len,char ***namelist, IS **islist, DM **dmlist)
1145 {
1146   PetscInt       nDM;
1147   PetscInt       i;
1148   PetscErrorCode ierr;
1149 
1150   PetscFunctionBegin;
1151   ierr = DMCreateFieldIS_Composite(dm, len, namelist, islist);CHKERRQ(ierr);
1152   if (dmlist) {
1153     ierr = DMCompositeGetNumberDM(dm, &nDM);CHKERRQ(ierr);
1154     ierr = PetscMalloc1(nDM, dmlist);CHKERRQ(ierr);
1155     ierr = DMCompositeGetEntriesArray(dm, *dmlist);CHKERRQ(ierr);
1156     for (i=0; i<nDM; i++) {
1157       ierr = PetscObjectReference((PetscObject)((*dmlist)[i]));CHKERRQ(ierr);
1158     }
1159   }
1160   PetscFunctionReturn(0);
1161 }
1162 
1163 
1164 
1165 /* -------------------------------------------------------------------------------------*/
1166 /*@C
1167     DMCompositeGetLocalVectors - Gets local vectors for each part of a DMComposite.
1168        Use DMCompositeRestoreLocalVectors() to return them.
1169 
1170     Not Collective
1171 
1172     Input Parameter:
1173 .    dm - the packer object
1174 
1175     Output Parameter:
1176 .   Vec ... - the individual sequential Vecs
1177 
1178     Level: advanced
1179 
1180     Not available from Fortran
1181 
1182 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
1183          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
1184          DMCompositeRestoreLocalVectors(), DMCompositeScatter(), DMCompositeGetEntries()
1185 
1186 @*/
1187 PetscErrorCode  DMCompositeGetLocalVectors(DM dm,...)
1188 {
1189   va_list                Argp;
1190   PetscErrorCode         ierr;
1191   struct DMCompositeLink *next;
1192   DM_Composite           *com = (DM_Composite*)dm->data;
1193   PetscBool              flg;
1194 
1195   PetscFunctionBegin;
1196   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1197   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
1198   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
1199   next = com->next;
1200   /* loop over packed objects, handling one at at time */
1201   va_start(Argp,dm);
1202   while (next) {
1203     Vec *vec;
1204     vec = va_arg(Argp, Vec*);
1205     if (vec) {ierr = DMGetLocalVector(next->dm,vec);CHKERRQ(ierr);}
1206     next = next->next;
1207   }
1208   va_end(Argp);
1209   PetscFunctionReturn(0);
1210 }
1211 
1212 /*@C
1213     DMCompositeRestoreLocalVectors - Restores local vectors for each part of a DMComposite.
1214 
1215     Not Collective
1216 
1217     Input Parameter:
1218 .    dm - the packer object
1219 
1220     Output Parameter:
1221 .   Vec ... - the individual sequential Vecs
1222 
1223     Level: advanced
1224 
1225     Not available from Fortran
1226 
1227 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
1228          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
1229          DMCompositeGetLocalVectors(), DMCompositeScatter(), DMCompositeGetEntries()
1230 
1231 @*/
1232 PetscErrorCode  DMCompositeRestoreLocalVectors(DM dm,...)
1233 {
1234   va_list                Argp;
1235   PetscErrorCode         ierr;
1236   struct DMCompositeLink *next;
1237   DM_Composite           *com = (DM_Composite*)dm->data;
1238   PetscBool              flg;
1239 
1240   PetscFunctionBegin;
1241   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1242   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
1243   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
1244   next = com->next;
1245   /* loop over packed objects, handling one at at time */
1246   va_start(Argp,dm);
1247   while (next) {
1248     Vec *vec;
1249     vec = va_arg(Argp, Vec*);
1250     if (vec) {ierr = DMRestoreLocalVector(next->dm,vec);CHKERRQ(ierr);}
1251     next = next->next;
1252   }
1253   va_end(Argp);
1254   PetscFunctionReturn(0);
1255 }
1256 
1257 /* -------------------------------------------------------------------------------------*/
1258 /*@C
1259     DMCompositeGetEntries - Gets the DM for each entry in a DMComposite.
1260 
1261     Not Collective
1262 
1263     Input Parameter:
1264 .    dm - the packer object
1265 
1266     Output Parameter:
1267 .   DM ... - the individual entries (DMs)
1268 
1269     Level: advanced
1270 
1271     Fortran Notes:
1272     Available as DMCompositeGetEntries() for one output DM, DMCompositeGetEntries2() for 2, etc
1273 
1274 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(), DMCompositeGetEntriesArray()
1275          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
1276          DMCompositeRestoreLocalVectors(), DMCompositeGetLocalVectors(),  DMCompositeScatter(),
1277          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors()
1278 
1279 @*/
1280 PetscErrorCode  DMCompositeGetEntries(DM dm,...)
1281 {
1282   va_list                Argp;
1283   struct DMCompositeLink *next;
1284   DM_Composite           *com = (DM_Composite*)dm->data;
1285   PetscBool              flg;
1286   PetscErrorCode         ierr;
1287 
1288   PetscFunctionBegin;
1289   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1290   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
1291   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
1292   next = com->next;
1293   /* loop over packed objects, handling one at at time */
1294   va_start(Argp,dm);
1295   while (next) {
1296     DM *dmn;
1297     dmn = va_arg(Argp, DM*);
1298     if (dmn) *dmn = next->dm;
1299     next = next->next;
1300   }
1301   va_end(Argp);
1302   PetscFunctionReturn(0);
1303 }
1304 
1305 /*@C
1306     DMCompositeGetEntriesArray - Gets the DM for each entry in a DMComposite.
1307 
1308     Not Collective
1309 
1310     Input Parameter:
1311 .    dm - the packer object
1312 
1313     Output Parameter:
1314 .    dms - array of sufficient length (see DMCompositeGetNumberDM()) to hold the individual DMs
1315 
1316     Level: advanced
1317 
1318 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(), DMCompositeGetEntries()
1319          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
1320          DMCompositeRestoreLocalVectors(), DMCompositeGetLocalVectors(),  DMCompositeScatter(),
1321          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors()
1322 
1323 @*/
1324 PetscErrorCode DMCompositeGetEntriesArray(DM dm,DM dms[])
1325 {
1326   struct DMCompositeLink *next;
1327   DM_Composite           *com = (DM_Composite*)dm->data;
1328   PetscInt               i;
1329   PetscBool              flg;
1330   PetscErrorCode         ierr;
1331 
1332   PetscFunctionBegin;
1333   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1334   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
1335   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
1336   /* loop over packed objects, handling one at at time */
1337   for (next=com->next,i=0; next; next=next->next,i++) dms[i] = next->dm;
1338   PetscFunctionReturn(0);
1339 }
1340 
1341 typedef struct {
1342   DM          dm;
1343   PetscViewer *subv;
1344   Vec         *vecs;
1345 } GLVisViewerCtx;
1346 
1347 static PetscErrorCode  DestroyGLVisViewerCtx_Private(void *vctx)
1348 {
1349   GLVisViewerCtx *ctx = (GLVisViewerCtx*)vctx;
1350   PetscInt       i,n;
1351   PetscErrorCode ierr;
1352 
1353   PetscFunctionBegin;
1354   ierr = DMCompositeGetNumberDM(ctx->dm,&n);CHKERRQ(ierr);
1355   for (i = 0; i < n; i++) {
1356     ierr = PetscViewerDestroy(&ctx->subv[i]);CHKERRQ(ierr);
1357   }
1358   ierr = PetscFree2(ctx->subv,ctx->vecs);CHKERRQ(ierr);
1359   ierr = DMDestroy(&ctx->dm);CHKERRQ(ierr);
1360   ierr = PetscFree(ctx);CHKERRQ(ierr);
1361   PetscFunctionReturn(0);
1362 }
1363 
1364 static PetscErrorCode  DMCompositeSampleGLVisFields_Private(PetscObject oX, PetscInt nf, PetscObject oXfield[], void *vctx)
1365 {
1366   Vec            X = (Vec)oX;
1367   GLVisViewerCtx *ctx = (GLVisViewerCtx*)vctx;
1368   PetscInt       i,n,cumf;
1369   PetscErrorCode ierr;
1370 
1371   PetscFunctionBegin;
1372   ierr = DMCompositeGetNumberDM(ctx->dm,&n);CHKERRQ(ierr);
1373   ierr = DMCompositeGetAccessArray(ctx->dm,X,n,NULL,ctx->vecs);CHKERRQ(ierr);
1374   for (i = 0, cumf = 0; i < n; i++) {
1375     PetscErrorCode (*g2l)(PetscObject,PetscInt,PetscObject[],void*);
1376     void           *fctx;
1377     PetscInt       nfi;
1378 
1379     ierr = PetscViewerGLVisGetFields_Private(ctx->subv[i],&nfi,NULL,NULL,&g2l,NULL,&fctx);CHKERRQ(ierr);
1380     if (!nfi) continue;
1381     if (g2l) {
1382       ierr = (*g2l)((PetscObject)ctx->vecs[i],nfi,oXfield+cumf,fctx);CHKERRQ(ierr);
1383     } else {
1384       ierr = VecCopy(ctx->vecs[i],(Vec)(oXfield[cumf]));CHKERRQ(ierr);
1385     }
1386     cumf += nfi;
1387   }
1388   ierr = DMCompositeRestoreAccessArray(ctx->dm,X,n,NULL,ctx->vecs);CHKERRQ(ierr);
1389   PetscFunctionReturn(0);
1390 }
1391 
1392 static PetscErrorCode  DMSetUpGLVisViewer_Composite(PetscObject odm, PetscViewer viewer)
1393 {
1394   DM             dm = (DM)odm, *dms;
1395   Vec            *Ufds;
1396   GLVisViewerCtx *ctx;
1397   PetscInt       i,n,tnf,*sdim;
1398   char           **fecs;
1399   PetscErrorCode ierr;
1400 
1401   PetscFunctionBegin;
1402   ierr = PetscNew(&ctx);CHKERRQ(ierr);
1403   ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
1404   ctx->dm = dm;
1405   ierr = DMCompositeGetNumberDM(dm,&n);CHKERRQ(ierr);
1406   ierr = PetscMalloc1(n,&dms);CHKERRQ(ierr);
1407   ierr = DMCompositeGetEntriesArray(dm,dms);CHKERRQ(ierr);
1408   ierr = PetscMalloc2(n,&ctx->subv,n,&ctx->vecs);CHKERRQ(ierr);
1409   for (i = 0, tnf = 0; i < n; i++) {
1410     PetscInt nf;
1411 
1412     ierr = PetscViewerCreate(PetscObjectComm(odm),&ctx->subv[i]);CHKERRQ(ierr);
1413     ierr = PetscViewerSetType(ctx->subv[i],PETSCVIEWERGLVIS);CHKERRQ(ierr);
1414     ierr = PetscViewerGLVisSetDM_Private(ctx->subv[i],(PetscObject)dms[i]);CHKERRQ(ierr);
1415     ierr = PetscViewerGLVisGetFields_Private(ctx->subv[i],&nf,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
1416     tnf += nf;
1417   }
1418   ierr = PetscFree(dms);CHKERRQ(ierr);
1419   ierr = PetscMalloc3(tnf,&fecs,tnf,&sdim,tnf,&Ufds);CHKERRQ(ierr);
1420   for (i = 0, tnf = 0; i < n; i++) {
1421     PetscInt   *sd,nf,f;
1422     const char **fec;
1423     Vec        *Uf;
1424 
1425     ierr = PetscViewerGLVisGetFields_Private(ctx->subv[i],&nf,&fec,&sd,NULL,(PetscObject**)&Uf,NULL);CHKERRQ(ierr);
1426     for (f = 0; f < nf; f++) {
1427       ierr = PetscStrallocpy(fec[f],&fecs[tnf+f]);CHKERRQ(ierr);
1428       Ufds[tnf+f] = Uf[f];
1429       sdim[tnf+f] = sd[f];
1430     }
1431     tnf += nf;
1432   }
1433   ierr = PetscViewerGLVisSetFields(viewer,tnf,(const char**)fecs,sdim,DMCompositeSampleGLVisFields_Private,(PetscObject*)Ufds,ctx,DestroyGLVisViewerCtx_Private);CHKERRQ(ierr);
1434   for (i = 0; i < tnf; i++) {
1435     ierr = PetscFree(fecs[i]);CHKERRQ(ierr);
1436   }
1437   ierr = PetscFree3(fecs,sdim,Ufds);CHKERRQ(ierr);
1438   PetscFunctionReturn(0);
1439 }
1440 
1441 PetscErrorCode  DMRefine_Composite(DM dmi,MPI_Comm comm,DM *fine)
1442 {
1443   PetscErrorCode         ierr;
1444   struct DMCompositeLink *next;
1445   DM_Composite           *com = (DM_Composite*)dmi->data;
1446   DM                     dm;
1447 
1448   PetscFunctionBegin;
1449   PetscValidHeaderSpecific(dmi,DM_CLASSID,1);
1450   if (comm == MPI_COMM_NULL) {
1451     ierr = PetscObjectGetComm((PetscObject)dmi,&comm);CHKERRQ(ierr);
1452   }
1453   ierr = DMSetUp(dmi);CHKERRQ(ierr);
1454   next = com->next;
1455   ierr = DMCompositeCreate(comm,fine);CHKERRQ(ierr);
1456 
1457   /* loop over packed objects, handling one at at time */
1458   while (next) {
1459     ierr = DMRefine(next->dm,comm,&dm);CHKERRQ(ierr);
1460     ierr = DMCompositeAddDM(*fine,dm);CHKERRQ(ierr);
1461     ierr = PetscObjectDereference((PetscObject)dm);CHKERRQ(ierr);
1462     next = next->next;
1463   }
1464   PetscFunctionReturn(0);
1465 }
1466 
1467 PetscErrorCode  DMCoarsen_Composite(DM dmi,MPI_Comm comm,DM *fine)
1468 {
1469   PetscErrorCode         ierr;
1470   struct DMCompositeLink *next;
1471   DM_Composite           *com = (DM_Composite*)dmi->data;
1472   DM                     dm;
1473 
1474   PetscFunctionBegin;
1475   PetscValidHeaderSpecific(dmi,DM_CLASSID,1);
1476   ierr = DMSetUp(dmi);CHKERRQ(ierr);
1477   if (comm == MPI_COMM_NULL) {
1478     ierr = PetscObjectGetComm((PetscObject)dmi,&comm);CHKERRQ(ierr);
1479   }
1480   next = com->next;
1481   ierr = DMCompositeCreate(comm,fine);CHKERRQ(ierr);
1482 
1483   /* loop over packed objects, handling one at at time */
1484   while (next) {
1485     ierr = DMCoarsen(next->dm,comm,&dm);CHKERRQ(ierr);
1486     ierr = DMCompositeAddDM(*fine,dm);CHKERRQ(ierr);
1487     ierr = PetscObjectDereference((PetscObject)dm);CHKERRQ(ierr);
1488     next = next->next;
1489   }
1490   PetscFunctionReturn(0);
1491 }
1492 
1493 PetscErrorCode  DMCreateInterpolation_Composite(DM coarse,DM fine,Mat *A,Vec *v)
1494 {
1495   PetscErrorCode         ierr;
1496   PetscInt               m,n,M,N,nDM,i;
1497   struct DMCompositeLink *nextc;
1498   struct DMCompositeLink *nextf;
1499   Vec                    gcoarse,gfine,*vecs;
1500   DM_Composite           *comcoarse = (DM_Composite*)coarse->data;
1501   DM_Composite           *comfine   = (DM_Composite*)fine->data;
1502   Mat                    *mats;
1503 
1504   PetscFunctionBegin;
1505   PetscValidHeaderSpecific(coarse,DM_CLASSID,1);
1506   PetscValidHeaderSpecific(fine,DM_CLASSID,2);
1507   ierr = DMSetUp(coarse);CHKERRQ(ierr);
1508   ierr = DMSetUp(fine);CHKERRQ(ierr);
1509   /* use global vectors only for determining matrix layout */
1510   ierr = DMGetGlobalVector(coarse,&gcoarse);CHKERRQ(ierr);
1511   ierr = DMGetGlobalVector(fine,&gfine);CHKERRQ(ierr);
1512   ierr = VecGetLocalSize(gcoarse,&n);CHKERRQ(ierr);
1513   ierr = VecGetLocalSize(gfine,&m);CHKERRQ(ierr);
1514   ierr = VecGetSize(gcoarse,&N);CHKERRQ(ierr);
1515   ierr = VecGetSize(gfine,&M);CHKERRQ(ierr);
1516   ierr = DMRestoreGlobalVector(coarse,&gcoarse);CHKERRQ(ierr);
1517   ierr = DMRestoreGlobalVector(fine,&gfine);CHKERRQ(ierr);
1518 
1519   nDM = comfine->nDM;
1520   if (nDM != comcoarse->nDM) SETERRQ2(PetscObjectComm((PetscObject)fine),PETSC_ERR_ARG_INCOMP,"Fine DMComposite has %D entries, but coarse has %D",nDM,comcoarse->nDM);
1521   ierr = PetscCalloc1(nDM*nDM,&mats);CHKERRQ(ierr);
1522   if (v) {
1523     ierr = PetscCalloc1(nDM,&vecs);CHKERRQ(ierr);
1524   }
1525 
1526   /* loop over packed objects, handling one at at time */
1527   for (nextc=comcoarse->next,nextf=comfine->next,i=0; nextc; nextc=nextc->next,nextf=nextf->next,i++) {
1528     if (!v) {
1529       ierr = DMCreateInterpolation(nextc->dm,nextf->dm,&mats[i*nDM+i],NULL);CHKERRQ(ierr);
1530     } else {
1531       ierr = DMCreateInterpolation(nextc->dm,nextf->dm,&mats[i*nDM+i],&vecs[i]);CHKERRQ(ierr);
1532     }
1533   }
1534   ierr = MatCreateNest(PetscObjectComm((PetscObject)fine),nDM,NULL,nDM,NULL,mats,A);CHKERRQ(ierr);
1535   if (v) {
1536     ierr = VecCreateNest(PetscObjectComm((PetscObject)fine),nDM,NULL,vecs,v);CHKERRQ(ierr);
1537   }
1538   for (i=0; i<nDM*nDM; i++) {ierr = MatDestroy(&mats[i]);CHKERRQ(ierr);}
1539   ierr = PetscFree(mats);CHKERRQ(ierr);
1540   if (v) {
1541     for (i=0; i<nDM; i++) {ierr = VecDestroy(&vecs[i]);CHKERRQ(ierr);}
1542     ierr = PetscFree(vecs);CHKERRQ(ierr);
1543   }
1544   PetscFunctionReturn(0);
1545 }
1546 
1547 static PetscErrorCode DMGetLocalToGlobalMapping_Composite(DM dm)
1548 {
1549   DM_Composite           *com = (DM_Composite*)dm->data;
1550   ISLocalToGlobalMapping *ltogs;
1551   PetscInt               i;
1552   PetscErrorCode         ierr;
1553 
1554   PetscFunctionBegin;
1555   /* Set the ISLocalToGlobalMapping on the new matrix */
1556   ierr = DMCompositeGetISLocalToGlobalMappings(dm,&ltogs);CHKERRQ(ierr);
1557   ierr = ISLocalToGlobalMappingConcatenate(PetscObjectComm((PetscObject)dm),com->nDM,ltogs,&dm->ltogmap);CHKERRQ(ierr);
1558   for (i=0; i<com->nDM; i++) {ierr = ISLocalToGlobalMappingDestroy(&ltogs[i]);CHKERRQ(ierr);}
1559   ierr = PetscFree(ltogs);CHKERRQ(ierr);
1560   PetscFunctionReturn(0);
1561 }
1562 
1563 
1564 PetscErrorCode  DMCreateColoring_Composite(DM dm,ISColoringType ctype,ISColoring *coloring)
1565 {
1566   PetscErrorCode  ierr;
1567   PetscInt        n,i,cnt;
1568   ISColoringValue *colors;
1569   PetscBool       dense  = PETSC_FALSE;
1570   ISColoringValue maxcol = 0;
1571   DM_Composite    *com   = (DM_Composite*)dm->data;
1572 
1573   PetscFunctionBegin;
1574   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1575   if (ctype == IS_COLORING_LOCAL) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only global coloring supported");
1576   else if (ctype == IS_COLORING_GLOBAL) {
1577     n = com->n;
1578   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Unknown ISColoringType");
1579   ierr = PetscMalloc1(n,&colors);CHKERRQ(ierr); /* freed in ISColoringDestroy() */
1580 
1581   ierr = PetscOptionsGetBool(((PetscObject)dm)->options,((PetscObject)dm)->prefix,"-dmcomposite_dense_jacobian",&dense,NULL);CHKERRQ(ierr);
1582   if (dense) {
1583     for (i=0; i<n; i++) {
1584       colors[i] = (ISColoringValue)(com->rstart + i);
1585     }
1586     maxcol = com->N;
1587   } else {
1588     struct DMCompositeLink *next = com->next;
1589     PetscMPIInt            rank;
1590 
1591     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
1592     cnt  = 0;
1593     while (next) {
1594       ISColoring lcoloring;
1595 
1596       ierr = DMCreateColoring(next->dm,IS_COLORING_GLOBAL,&lcoloring);CHKERRQ(ierr);
1597       for (i=0; i<lcoloring->N; i++) {
1598         colors[cnt++] = maxcol + lcoloring->colors[i];
1599       }
1600       maxcol += lcoloring->n;
1601       ierr    = ISColoringDestroy(&lcoloring);CHKERRQ(ierr);
1602       next    = next->next;
1603     }
1604   }
1605   ierr = ISColoringCreate(PetscObjectComm((PetscObject)dm),maxcol,n,colors,PETSC_OWN_POINTER,coloring);CHKERRQ(ierr);
1606   PetscFunctionReturn(0);
1607 }
1608 
1609 PetscErrorCode  DMGlobalToLocalBegin_Composite(DM dm,Vec gvec,InsertMode mode,Vec lvec)
1610 {
1611   PetscErrorCode         ierr;
1612   struct DMCompositeLink *next;
1613   PetscScalar            *garray,*larray;
1614   DM_Composite           *com = (DM_Composite*)dm->data;
1615 
1616   PetscFunctionBegin;
1617   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1618   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
1619 
1620   if (!com->setup) {
1621     ierr = DMSetUp(dm);CHKERRQ(ierr);
1622   }
1623 
1624   ierr = VecGetArray(gvec,&garray);CHKERRQ(ierr);
1625   ierr = VecGetArray(lvec,&larray);CHKERRQ(ierr);
1626 
1627   /* loop over packed objects, handling one at at time */
1628   next = com->next;
1629   while (next) {
1630     Vec      local,global;
1631     PetscInt N;
1632 
1633     ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
1634     ierr = VecGetLocalSize(global,&N);CHKERRQ(ierr);
1635     ierr = VecPlaceArray(global,garray);CHKERRQ(ierr);
1636     ierr = DMGetLocalVector(next->dm,&local);CHKERRQ(ierr);
1637     ierr = VecPlaceArray(local,larray);CHKERRQ(ierr);
1638     ierr = DMGlobalToLocalBegin(next->dm,global,mode,local);CHKERRQ(ierr);
1639     ierr = DMGlobalToLocalEnd(next->dm,global,mode,local);CHKERRQ(ierr);
1640     ierr = VecResetArray(global);CHKERRQ(ierr);
1641     ierr = VecResetArray(local);CHKERRQ(ierr);
1642     ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
1643     ierr = DMRestoreLocalVector(next->dm,&local);CHKERRQ(ierr);
1644 
1645     larray += next->nlocal;
1646     garray += next->n;
1647     next    = next->next;
1648   }
1649 
1650   ierr = VecRestoreArray(gvec,NULL);CHKERRQ(ierr);
1651   ierr = VecRestoreArray(lvec,NULL);CHKERRQ(ierr);
1652   PetscFunctionReturn(0);
1653 }
1654 
1655 PetscErrorCode  DMGlobalToLocalEnd_Composite(DM dm,Vec gvec,InsertMode mode,Vec lvec)
1656 {
1657   PetscFunctionBegin;
1658   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1659   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
1660   PetscValidHeaderSpecific(lvec,VEC_CLASSID,4);
1661   PetscFunctionReturn(0);
1662 }
1663 
1664 PetscErrorCode  DMLocalToGlobalBegin_Composite(DM dm,Vec lvec,InsertMode mode,Vec gvec)
1665 {
1666   PetscErrorCode         ierr;
1667   struct DMCompositeLink *next;
1668   PetscScalar            *larray,*garray;
1669   DM_Composite           *com = (DM_Composite*)dm->data;
1670 
1671   PetscFunctionBegin;
1672   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1673   PetscValidHeaderSpecific(lvec,VEC_CLASSID,2);
1674   PetscValidHeaderSpecific(gvec,VEC_CLASSID,4);
1675 
1676   if (!com->setup) {
1677     ierr = DMSetUp(dm);CHKERRQ(ierr);
1678   }
1679 
1680   ierr = VecGetArray(lvec,&larray);CHKERRQ(ierr);
1681   ierr = VecGetArray(gvec,&garray);CHKERRQ(ierr);
1682 
1683   /* loop over packed objects, handling one at at time */
1684   next = com->next;
1685   while (next) {
1686     Vec      global,local;
1687 
1688     ierr = DMGetLocalVector(next->dm,&local);CHKERRQ(ierr);
1689     ierr = VecPlaceArray(local,larray);CHKERRQ(ierr);
1690     ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
1691     ierr = VecPlaceArray(global,garray);CHKERRQ(ierr);
1692     ierr = DMLocalToGlobalBegin(next->dm,local,mode,global);CHKERRQ(ierr);
1693     ierr = DMLocalToGlobalEnd(next->dm,local,mode,global);CHKERRQ(ierr);
1694     ierr = VecResetArray(local);CHKERRQ(ierr);
1695     ierr = VecResetArray(global);CHKERRQ(ierr);
1696     ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
1697     ierr = DMRestoreLocalVector(next->dm,&local);CHKERRQ(ierr);
1698 
1699     garray += next->n;
1700     larray += next->nlocal;
1701     next    = next->next;
1702   }
1703 
1704   ierr = VecRestoreArray(gvec,NULL);CHKERRQ(ierr);
1705   ierr = VecRestoreArray(lvec,NULL);CHKERRQ(ierr);
1706 
1707   PetscFunctionReturn(0);
1708 }
1709 
1710 PetscErrorCode  DMLocalToGlobalEnd_Composite(DM dm,Vec lvec,InsertMode mode,Vec gvec)
1711 {
1712   PetscFunctionBegin;
1713   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1714   PetscValidHeaderSpecific(lvec,VEC_CLASSID,2);
1715   PetscValidHeaderSpecific(gvec,VEC_CLASSID,4);
1716   PetscFunctionReturn(0);
1717 }
1718 
1719 PetscErrorCode  DMLocalToLocalBegin_Composite(DM dm,Vec vec1,InsertMode mode,Vec vec2)
1720 {
1721   PetscErrorCode         ierr;
1722   struct DMCompositeLink *next;
1723   PetscScalar            *array1,*array2;
1724   DM_Composite           *com = (DM_Composite*)dm->data;
1725 
1726   PetscFunctionBegin;
1727   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1728   PetscValidHeaderSpecific(vec1,VEC_CLASSID,2);
1729   PetscValidHeaderSpecific(vec2,VEC_CLASSID,4);
1730 
1731   if (!com->setup) {
1732     ierr = DMSetUp(dm);CHKERRQ(ierr);
1733   }
1734 
1735   ierr = VecGetArray(vec1,&array1);CHKERRQ(ierr);
1736   ierr = VecGetArray(vec2,&array2);CHKERRQ(ierr);
1737 
1738   /* loop over packed objects, handling one at at time */
1739   next = com->next;
1740   while (next) {
1741     Vec      local1,local2;
1742 
1743     ierr = DMGetLocalVector(next->dm,&local1);CHKERRQ(ierr);
1744     ierr = VecPlaceArray(local1,array1);CHKERRQ(ierr);
1745     ierr = DMGetLocalVector(next->dm,&local2);CHKERRQ(ierr);
1746     ierr = VecPlaceArray(local2,array2);CHKERRQ(ierr);
1747     ierr = DMLocalToLocalBegin(next->dm,local1,mode,local2);CHKERRQ(ierr);
1748     ierr = DMLocalToLocalEnd(next->dm,local1,mode,local2);CHKERRQ(ierr);
1749     ierr = VecResetArray(local2);CHKERRQ(ierr);
1750     ierr = DMRestoreLocalVector(next->dm,&local2);CHKERRQ(ierr);
1751     ierr = VecResetArray(local1);CHKERRQ(ierr);
1752     ierr = DMRestoreLocalVector(next->dm,&local1);CHKERRQ(ierr);
1753 
1754     array1 += next->nlocal;
1755     array2 += next->nlocal;
1756     next    = next->next;
1757   }
1758 
1759   ierr = VecRestoreArray(vec1,NULL);CHKERRQ(ierr);
1760   ierr = VecRestoreArray(vec2,NULL);CHKERRQ(ierr);
1761 
1762   PetscFunctionReturn(0);
1763 }
1764 
1765 PetscErrorCode  DMLocalToLocalEnd_Composite(DM dm,Vec lvec,InsertMode mode,Vec gvec)
1766 {
1767   PetscFunctionBegin;
1768   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1769   PetscValidHeaderSpecific(lvec,VEC_CLASSID,2);
1770   PetscValidHeaderSpecific(gvec,VEC_CLASSID,4);
1771   PetscFunctionReturn(0);
1772 }
1773 
1774 /*MC
1775    DMCOMPOSITE = "composite" - A DM object that is used to manage data for a collection of DMs
1776 
1777   Level: intermediate
1778 
1779 .seealso: DMType, DM, DMDACreate(), DMCreate(), DMSetType(), DMCompositeCreate()
1780 M*/
1781 
1782 
1783 PETSC_EXTERN PetscErrorCode DMCreate_Composite(DM p)
1784 {
1785   PetscErrorCode ierr;
1786   DM_Composite   *com;
1787 
1788   PetscFunctionBegin;
1789   ierr          = PetscNewLog(p,&com);CHKERRQ(ierr);
1790   p->data       = com;
1791   ierr          = PetscObjectChangeTypeName((PetscObject)p,"DMComposite");CHKERRQ(ierr);
1792   com->n        = 0;
1793   com->nghost   = 0;
1794   com->next     = NULL;
1795   com->nDM      = 0;
1796 
1797   p->ops->createglobalvector              = DMCreateGlobalVector_Composite;
1798   p->ops->createlocalvector               = DMCreateLocalVector_Composite;
1799   p->ops->getlocaltoglobalmapping         = DMGetLocalToGlobalMapping_Composite;
1800   p->ops->createfieldis                   = DMCreateFieldIS_Composite;
1801   p->ops->createfielddecomposition        = DMCreateFieldDecomposition_Composite;
1802   p->ops->refine                          = DMRefine_Composite;
1803   p->ops->coarsen                         = DMCoarsen_Composite;
1804   p->ops->createinterpolation             = DMCreateInterpolation_Composite;
1805   p->ops->creatematrix                    = DMCreateMatrix_Composite;
1806   p->ops->getcoloring                     = DMCreateColoring_Composite;
1807   p->ops->globaltolocalbegin              = DMGlobalToLocalBegin_Composite;
1808   p->ops->globaltolocalend                = DMGlobalToLocalEnd_Composite;
1809   p->ops->localtoglobalbegin              = DMLocalToGlobalBegin_Composite;
1810   p->ops->localtoglobalend                = DMLocalToGlobalEnd_Composite;
1811   p->ops->localtolocalbegin               = DMLocalToLocalBegin_Composite;
1812   p->ops->localtolocalend                 = DMLocalToLocalEnd_Composite;
1813   p->ops->destroy                         = DMDestroy_Composite;
1814   p->ops->view                            = DMView_Composite;
1815   p->ops->setup                           = DMSetUp_Composite;
1816 
1817   ierr = PetscObjectComposeFunction((PetscObject)p,"DMSetUpGLVisViewer_C",DMSetUpGLVisViewer_Composite);CHKERRQ(ierr);
1818   PetscFunctionReturn(0);
1819 }
1820 
1821 /*@
1822     DMCompositeCreate - Creates a vector packer, used to generate "composite"
1823       vectors made up of several subvectors.
1824 
1825     Collective on MPI_Comm
1826 
1827     Input Parameter:
1828 .   comm - the processors that will share the global vector
1829 
1830     Output Parameters:
1831 .   packer - the packer object
1832 
1833     Level: advanced
1834 
1835 .seealso DMDestroy(), DMCompositeAddDM(), DMCompositeScatter(), DMCOMPOSITE,DMCreate()
1836          DMCompositeGather(), DMCreateGlobalVector(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess()
1837          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
1838 
1839 @*/
1840 PetscErrorCode  DMCompositeCreate(MPI_Comm comm,DM *packer)
1841 {
1842   PetscErrorCode ierr;
1843 
1844   PetscFunctionBegin;
1845   PetscValidPointer(packer,2);
1846   ierr = DMCreate(comm,packer);CHKERRQ(ierr);
1847   ierr = DMSetType(*packer,DMCOMPOSITE);CHKERRQ(ierr);
1848   PetscFunctionReturn(0);
1849 }
1850