xref: /petsc/src/dm/impls/composite/pack.c (revision bfcb38ea38335faa6e7f8d97f6bc6ce9aa2a1dd1)
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 = VecLockReadPush(*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 = VecLockReadPush(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 = VecLockReadPush(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 = VecLockReadPop(*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 = VecLockReadPop(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 = VecLockReadPop(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     PetscDS prob;
1073 
1074     ierr = ISCreateStride(PetscObjectComm((PetscObject)dm),next->n,next->grstart,1,&(*is)[cnt]);CHKERRQ(ierr);
1075     ierr = DMGetDS(dm, &prob);CHKERRQ(ierr);
1076     if (prob) {
1077       MatNullSpace space;
1078       Mat          pmat;
1079       PetscObject  disc;
1080       PetscInt     Nf;
1081 
1082       ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
1083       if (cnt < Nf) {
1084         ierr = PetscDSGetDiscretization(prob, cnt, &disc);CHKERRQ(ierr);
1085         ierr = PetscObjectQuery(disc, "nullspace", (PetscObject*) &space);CHKERRQ(ierr);
1086         if (space) {ierr = PetscObjectCompose((PetscObject) (*is)[cnt], "nullspace", (PetscObject) space);CHKERRQ(ierr);}
1087         ierr = PetscObjectQuery(disc, "nearnullspace", (PetscObject*) &space);CHKERRQ(ierr);
1088         if (space) {ierr = PetscObjectCompose((PetscObject) (*is)[cnt], "nearnullspace", (PetscObject) space);CHKERRQ(ierr);}
1089         ierr = PetscObjectQuery(disc, "pmat", (PetscObject*) &pmat);CHKERRQ(ierr);
1090         if (pmat) {ierr = PetscObjectCompose((PetscObject) (*is)[cnt], "pmat", (PetscObject) pmat);CHKERRQ(ierr);}
1091       }
1092     }
1093     cnt++;
1094     next = next->next;
1095   }
1096   PetscFunctionReturn(0);
1097 }
1098 
1099 PetscErrorCode DMCreateFieldIS_Composite(DM dm, PetscInt *numFields,char ***fieldNames, IS **fields)
1100 {
1101   PetscInt       nDM;
1102   DM             *dms;
1103   PetscInt       i;
1104   PetscErrorCode ierr;
1105 
1106   PetscFunctionBegin;
1107   ierr = DMCompositeGetNumberDM(dm, &nDM);CHKERRQ(ierr);
1108   if (numFields) *numFields = nDM;
1109   ierr = DMCompositeGetGlobalISs(dm, fields);CHKERRQ(ierr);
1110   if (fieldNames) {
1111     ierr = PetscMalloc1(nDM, &dms);CHKERRQ(ierr);
1112     ierr = PetscMalloc1(nDM, fieldNames);CHKERRQ(ierr);
1113     ierr = DMCompositeGetEntriesArray(dm, dms);CHKERRQ(ierr);
1114     for (i=0; i<nDM; i++) {
1115       char       buf[256];
1116       const char *splitname;
1117 
1118       /* Split naming precedence: object name, prefix, number */
1119       splitname = ((PetscObject) dm)->name;
1120       if (!splitname) {
1121         ierr = PetscObjectGetOptionsPrefix((PetscObject)dms[i],&splitname);CHKERRQ(ierr);
1122         if (splitname) {
1123           size_t len;
1124           ierr                 = PetscStrncpy(buf,splitname,sizeof(buf));CHKERRQ(ierr);
1125           buf[sizeof(buf) - 1] = 0;
1126           ierr                 = PetscStrlen(buf,&len);CHKERRQ(ierr);
1127           if (buf[len-1] == '_') buf[len-1] = 0; /* Remove trailing underscore if it was used */
1128           splitname = buf;
1129         }
1130       }
1131       if (!splitname) {
1132         ierr      = PetscSNPrintf(buf,sizeof(buf),"%D",i);CHKERRQ(ierr);
1133         splitname = buf;
1134       }
1135       ierr = PetscStrallocpy(splitname,&(*fieldNames)[i]);CHKERRQ(ierr);
1136     }
1137     ierr = PetscFree(dms);CHKERRQ(ierr);
1138   }
1139   PetscFunctionReturn(0);
1140 }
1141 
1142 /*
1143  This could take over from DMCreateFieldIS(), as it is more general,
1144  making DMCreateFieldIS() a special case -- calling with dmlist == NULL;
1145  At this point it's probably best to be less intrusive, however.
1146  */
1147 PetscErrorCode DMCreateFieldDecomposition_Composite(DM dm, PetscInt *len,char ***namelist, IS **islist, DM **dmlist)
1148 {
1149   PetscInt       nDM;
1150   PetscInt       i;
1151   PetscErrorCode ierr;
1152 
1153   PetscFunctionBegin;
1154   ierr = DMCreateFieldIS_Composite(dm, len, namelist, islist);CHKERRQ(ierr);
1155   if (dmlist) {
1156     ierr = DMCompositeGetNumberDM(dm, &nDM);CHKERRQ(ierr);
1157     ierr = PetscMalloc1(nDM, dmlist);CHKERRQ(ierr);
1158     ierr = DMCompositeGetEntriesArray(dm, *dmlist);CHKERRQ(ierr);
1159     for (i=0; i<nDM; i++) {
1160       ierr = PetscObjectReference((PetscObject)((*dmlist)[i]));CHKERRQ(ierr);
1161     }
1162   }
1163   PetscFunctionReturn(0);
1164 }
1165 
1166 
1167 
1168 /* -------------------------------------------------------------------------------------*/
1169 /*@C
1170     DMCompositeGetLocalVectors - Gets local vectors for each part of a DMComposite.
1171        Use DMCompositeRestoreLocalVectors() to return them.
1172 
1173     Not Collective
1174 
1175     Input Parameter:
1176 .    dm - the packer object
1177 
1178     Output Parameter:
1179 .   Vec ... - the individual sequential Vecs
1180 
1181     Level: advanced
1182 
1183     Not available from Fortran
1184 
1185 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
1186          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
1187          DMCompositeRestoreLocalVectors(), DMCompositeScatter(), DMCompositeGetEntries()
1188 
1189 @*/
1190 PetscErrorCode  DMCompositeGetLocalVectors(DM dm,...)
1191 {
1192   va_list                Argp;
1193   PetscErrorCode         ierr;
1194   struct DMCompositeLink *next;
1195   DM_Composite           *com = (DM_Composite*)dm->data;
1196   PetscBool              flg;
1197 
1198   PetscFunctionBegin;
1199   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1200   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
1201   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
1202   next = com->next;
1203   /* loop over packed objects, handling one at at time */
1204   va_start(Argp,dm);
1205   while (next) {
1206     Vec *vec;
1207     vec = va_arg(Argp, Vec*);
1208     if (vec) {ierr = DMGetLocalVector(next->dm,vec);CHKERRQ(ierr);}
1209     next = next->next;
1210   }
1211   va_end(Argp);
1212   PetscFunctionReturn(0);
1213 }
1214 
1215 /*@C
1216     DMCompositeRestoreLocalVectors - Restores local vectors for each part of a DMComposite.
1217 
1218     Not Collective
1219 
1220     Input Parameter:
1221 .    dm - the packer object
1222 
1223     Output Parameter:
1224 .   Vec ... - the individual sequential Vecs
1225 
1226     Level: advanced
1227 
1228     Not available from Fortran
1229 
1230 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
1231          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
1232          DMCompositeGetLocalVectors(), DMCompositeScatter(), DMCompositeGetEntries()
1233 
1234 @*/
1235 PetscErrorCode  DMCompositeRestoreLocalVectors(DM dm,...)
1236 {
1237   va_list                Argp;
1238   PetscErrorCode         ierr;
1239   struct DMCompositeLink *next;
1240   DM_Composite           *com = (DM_Composite*)dm->data;
1241   PetscBool              flg;
1242 
1243   PetscFunctionBegin;
1244   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1245   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
1246   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
1247   next = com->next;
1248   /* loop over packed objects, handling one at at time */
1249   va_start(Argp,dm);
1250   while (next) {
1251     Vec *vec;
1252     vec = va_arg(Argp, Vec*);
1253     if (vec) {ierr = DMRestoreLocalVector(next->dm,vec);CHKERRQ(ierr);}
1254     next = next->next;
1255   }
1256   va_end(Argp);
1257   PetscFunctionReturn(0);
1258 }
1259 
1260 /* -------------------------------------------------------------------------------------*/
1261 /*@C
1262     DMCompositeGetEntries - Gets the DM for each entry in a DMComposite.
1263 
1264     Not Collective
1265 
1266     Input Parameter:
1267 .    dm - the packer object
1268 
1269     Output Parameter:
1270 .   DM ... - the individual entries (DMs)
1271 
1272     Level: advanced
1273 
1274     Fortran Notes:
1275     Available as DMCompositeGetEntries() for one output DM, DMCompositeGetEntries2() for 2, etc
1276 
1277 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(), DMCompositeGetEntriesArray()
1278          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
1279          DMCompositeRestoreLocalVectors(), DMCompositeGetLocalVectors(),  DMCompositeScatter(),
1280          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors()
1281 
1282 @*/
1283 PetscErrorCode  DMCompositeGetEntries(DM dm,...)
1284 {
1285   va_list                Argp;
1286   struct DMCompositeLink *next;
1287   DM_Composite           *com = (DM_Composite*)dm->data;
1288   PetscBool              flg;
1289   PetscErrorCode         ierr;
1290 
1291   PetscFunctionBegin;
1292   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1293   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
1294   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
1295   next = com->next;
1296   /* loop over packed objects, handling one at at time */
1297   va_start(Argp,dm);
1298   while (next) {
1299     DM *dmn;
1300     dmn = va_arg(Argp, DM*);
1301     if (dmn) *dmn = next->dm;
1302     next = next->next;
1303   }
1304   va_end(Argp);
1305   PetscFunctionReturn(0);
1306 }
1307 
1308 /*@C
1309     DMCompositeGetEntriesArray - Gets the DM for each entry in a DMComposite.
1310 
1311     Not Collective
1312 
1313     Input Parameter:
1314 .    dm - the packer object
1315 
1316     Output Parameter:
1317 .    dms - array of sufficient length (see DMCompositeGetNumberDM()) to hold the individual DMs
1318 
1319     Level: advanced
1320 
1321 .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(), DMCompositeGetEntries()
1322          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
1323          DMCompositeRestoreLocalVectors(), DMCompositeGetLocalVectors(),  DMCompositeScatter(),
1324          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors()
1325 
1326 @*/
1327 PetscErrorCode DMCompositeGetEntriesArray(DM dm,DM dms[])
1328 {
1329   struct DMCompositeLink *next;
1330   DM_Composite           *com = (DM_Composite*)dm->data;
1331   PetscInt               i;
1332   PetscBool              flg;
1333   PetscErrorCode         ierr;
1334 
1335   PetscFunctionBegin;
1336   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1337   ierr = PetscObjectTypeCompare((PetscObject)dm,DMCOMPOSITE,&flg);CHKERRQ(ierr);
1338   if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for type %s",((PetscObject)dm)->type_name);
1339   /* loop over packed objects, handling one at at time */
1340   for (next=com->next,i=0; next; next=next->next,i++) dms[i] = next->dm;
1341   PetscFunctionReturn(0);
1342 }
1343 
1344 typedef struct {
1345   DM          dm;
1346   PetscViewer *subv;
1347   Vec         *vecs;
1348 } GLVisViewerCtx;
1349 
1350 static PetscErrorCode  DestroyGLVisViewerCtx_Private(void *vctx)
1351 {
1352   GLVisViewerCtx *ctx = (GLVisViewerCtx*)vctx;
1353   PetscInt       i,n;
1354   PetscErrorCode ierr;
1355 
1356   PetscFunctionBegin;
1357   ierr = DMCompositeGetNumberDM(ctx->dm,&n);CHKERRQ(ierr);
1358   for (i = 0; i < n; i++) {
1359     ierr = PetscViewerDestroy(&ctx->subv[i]);CHKERRQ(ierr);
1360   }
1361   ierr = PetscFree2(ctx->subv,ctx->vecs);CHKERRQ(ierr);
1362   ierr = DMDestroy(&ctx->dm);CHKERRQ(ierr);
1363   ierr = PetscFree(ctx);CHKERRQ(ierr);
1364   PetscFunctionReturn(0);
1365 }
1366 
1367 static PetscErrorCode  DMCompositeSampleGLVisFields_Private(PetscObject oX, PetscInt nf, PetscObject oXfield[], void *vctx)
1368 {
1369   Vec            X = (Vec)oX;
1370   GLVisViewerCtx *ctx = (GLVisViewerCtx*)vctx;
1371   PetscInt       i,n,cumf;
1372   PetscErrorCode ierr;
1373 
1374   PetscFunctionBegin;
1375   ierr = DMCompositeGetNumberDM(ctx->dm,&n);CHKERRQ(ierr);
1376   ierr = DMCompositeGetAccessArray(ctx->dm,X,n,NULL,ctx->vecs);CHKERRQ(ierr);
1377   for (i = 0, cumf = 0; i < n; i++) {
1378     PetscErrorCode (*g2l)(PetscObject,PetscInt,PetscObject[],void*);
1379     void           *fctx;
1380     PetscInt       nfi;
1381 
1382     ierr = PetscViewerGLVisGetFields_Private(ctx->subv[i],&nfi,NULL,NULL,&g2l,NULL,&fctx);CHKERRQ(ierr);
1383     if (!nfi) continue;
1384     if (g2l) {
1385       ierr = (*g2l)((PetscObject)ctx->vecs[i],nfi,oXfield+cumf,fctx);CHKERRQ(ierr);
1386     } else {
1387       ierr = VecCopy(ctx->vecs[i],(Vec)(oXfield[cumf]));CHKERRQ(ierr);
1388     }
1389     cumf += nfi;
1390   }
1391   ierr = DMCompositeRestoreAccessArray(ctx->dm,X,n,NULL,ctx->vecs);CHKERRQ(ierr);
1392   PetscFunctionReturn(0);
1393 }
1394 
1395 static PetscErrorCode  DMSetUpGLVisViewer_Composite(PetscObject odm, PetscViewer viewer)
1396 {
1397   DM             dm = (DM)odm, *dms;
1398   Vec            *Ufds;
1399   GLVisViewerCtx *ctx;
1400   PetscInt       i,n,tnf,*sdim;
1401   char           **fecs;
1402   PetscErrorCode ierr;
1403 
1404   PetscFunctionBegin;
1405   ierr = PetscNew(&ctx);CHKERRQ(ierr);
1406   ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
1407   ctx->dm = dm;
1408   ierr = DMCompositeGetNumberDM(dm,&n);CHKERRQ(ierr);
1409   ierr = PetscMalloc1(n,&dms);CHKERRQ(ierr);
1410   ierr = DMCompositeGetEntriesArray(dm,dms);CHKERRQ(ierr);
1411   ierr = PetscMalloc2(n,&ctx->subv,n,&ctx->vecs);CHKERRQ(ierr);
1412   for (i = 0, tnf = 0; i < n; i++) {
1413     PetscInt nf;
1414 
1415     ierr = PetscViewerCreate(PetscObjectComm(odm),&ctx->subv[i]);CHKERRQ(ierr);
1416     ierr = PetscViewerSetType(ctx->subv[i],PETSCVIEWERGLVIS);CHKERRQ(ierr);
1417     ierr = PetscViewerGLVisSetDM_Private(ctx->subv[i],(PetscObject)dms[i]);CHKERRQ(ierr);
1418     ierr = PetscViewerGLVisGetFields_Private(ctx->subv[i],&nf,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
1419     tnf += nf;
1420   }
1421   ierr = PetscFree(dms);CHKERRQ(ierr);
1422   ierr = PetscMalloc3(tnf,&fecs,tnf,&sdim,tnf,&Ufds);CHKERRQ(ierr);
1423   for (i = 0, tnf = 0; i < n; i++) {
1424     PetscInt   *sd,nf,f;
1425     const char **fec;
1426     Vec        *Uf;
1427 
1428     ierr = PetscViewerGLVisGetFields_Private(ctx->subv[i],&nf,&fec,&sd,NULL,(PetscObject**)&Uf,NULL);CHKERRQ(ierr);
1429     for (f = 0; f < nf; f++) {
1430       ierr = PetscStrallocpy(fec[f],&fecs[tnf+f]);CHKERRQ(ierr);
1431       Ufds[tnf+f] = Uf[f];
1432       sdim[tnf+f] = sd[f];
1433     }
1434     tnf += nf;
1435   }
1436   ierr = PetscViewerGLVisSetFields(viewer,tnf,(const char**)fecs,sdim,DMCompositeSampleGLVisFields_Private,(PetscObject*)Ufds,ctx,DestroyGLVisViewerCtx_Private);CHKERRQ(ierr);
1437   for (i = 0; i < tnf; i++) {
1438     ierr = PetscFree(fecs[i]);CHKERRQ(ierr);
1439   }
1440   ierr = PetscFree3(fecs,sdim,Ufds);CHKERRQ(ierr);
1441   PetscFunctionReturn(0);
1442 }
1443 
1444 PetscErrorCode  DMRefine_Composite(DM dmi,MPI_Comm comm,DM *fine)
1445 {
1446   PetscErrorCode         ierr;
1447   struct DMCompositeLink *next;
1448   DM_Composite           *com = (DM_Composite*)dmi->data;
1449   DM                     dm;
1450 
1451   PetscFunctionBegin;
1452   PetscValidHeaderSpecific(dmi,DM_CLASSID,1);
1453   if (comm == MPI_COMM_NULL) {
1454     ierr = PetscObjectGetComm((PetscObject)dmi,&comm);CHKERRQ(ierr);
1455   }
1456   ierr = DMSetUp(dmi);CHKERRQ(ierr);
1457   next = com->next;
1458   ierr = DMCompositeCreate(comm,fine);CHKERRQ(ierr);
1459 
1460   /* loop over packed objects, handling one at at time */
1461   while (next) {
1462     ierr = DMRefine(next->dm,comm,&dm);CHKERRQ(ierr);
1463     ierr = DMCompositeAddDM(*fine,dm);CHKERRQ(ierr);
1464     ierr = PetscObjectDereference((PetscObject)dm);CHKERRQ(ierr);
1465     next = next->next;
1466   }
1467   PetscFunctionReturn(0);
1468 }
1469 
1470 PetscErrorCode  DMCoarsen_Composite(DM dmi,MPI_Comm comm,DM *fine)
1471 {
1472   PetscErrorCode         ierr;
1473   struct DMCompositeLink *next;
1474   DM_Composite           *com = (DM_Composite*)dmi->data;
1475   DM                     dm;
1476 
1477   PetscFunctionBegin;
1478   PetscValidHeaderSpecific(dmi,DM_CLASSID,1);
1479   ierr = DMSetUp(dmi);CHKERRQ(ierr);
1480   if (comm == MPI_COMM_NULL) {
1481     ierr = PetscObjectGetComm((PetscObject)dmi,&comm);CHKERRQ(ierr);
1482   }
1483   next = com->next;
1484   ierr = DMCompositeCreate(comm,fine);CHKERRQ(ierr);
1485 
1486   /* loop over packed objects, handling one at at time */
1487   while (next) {
1488     ierr = DMCoarsen(next->dm,comm,&dm);CHKERRQ(ierr);
1489     ierr = DMCompositeAddDM(*fine,dm);CHKERRQ(ierr);
1490     ierr = PetscObjectDereference((PetscObject)dm);CHKERRQ(ierr);
1491     next = next->next;
1492   }
1493   PetscFunctionReturn(0);
1494 }
1495 
1496 PetscErrorCode  DMCreateInterpolation_Composite(DM coarse,DM fine,Mat *A,Vec *v)
1497 {
1498   PetscErrorCode         ierr;
1499   PetscInt               m,n,M,N,nDM,i;
1500   struct DMCompositeLink *nextc;
1501   struct DMCompositeLink *nextf;
1502   Vec                    gcoarse,gfine,*vecs;
1503   DM_Composite           *comcoarse = (DM_Composite*)coarse->data;
1504   DM_Composite           *comfine   = (DM_Composite*)fine->data;
1505   Mat                    *mats;
1506 
1507   PetscFunctionBegin;
1508   PetscValidHeaderSpecific(coarse,DM_CLASSID,1);
1509   PetscValidHeaderSpecific(fine,DM_CLASSID,2);
1510   ierr = DMSetUp(coarse);CHKERRQ(ierr);
1511   ierr = DMSetUp(fine);CHKERRQ(ierr);
1512   /* use global vectors only for determining matrix layout */
1513   ierr = DMGetGlobalVector(coarse,&gcoarse);CHKERRQ(ierr);
1514   ierr = DMGetGlobalVector(fine,&gfine);CHKERRQ(ierr);
1515   ierr = VecGetLocalSize(gcoarse,&n);CHKERRQ(ierr);
1516   ierr = VecGetLocalSize(gfine,&m);CHKERRQ(ierr);
1517   ierr = VecGetSize(gcoarse,&N);CHKERRQ(ierr);
1518   ierr = VecGetSize(gfine,&M);CHKERRQ(ierr);
1519   ierr = DMRestoreGlobalVector(coarse,&gcoarse);CHKERRQ(ierr);
1520   ierr = DMRestoreGlobalVector(fine,&gfine);CHKERRQ(ierr);
1521 
1522   nDM = comfine->nDM;
1523   if (nDM != comcoarse->nDM) SETERRQ2(PetscObjectComm((PetscObject)fine),PETSC_ERR_ARG_INCOMP,"Fine DMComposite has %D entries, but coarse has %D",nDM,comcoarse->nDM);
1524   ierr = PetscCalloc1(nDM*nDM,&mats);CHKERRQ(ierr);
1525   if (v) {
1526     ierr = PetscCalloc1(nDM,&vecs);CHKERRQ(ierr);
1527   }
1528 
1529   /* loop over packed objects, handling one at at time */
1530   for (nextc=comcoarse->next,nextf=comfine->next,i=0; nextc; nextc=nextc->next,nextf=nextf->next,i++) {
1531     if (!v) {
1532       ierr = DMCreateInterpolation(nextc->dm,nextf->dm,&mats[i*nDM+i],NULL);CHKERRQ(ierr);
1533     } else {
1534       ierr = DMCreateInterpolation(nextc->dm,nextf->dm,&mats[i*nDM+i],&vecs[i]);CHKERRQ(ierr);
1535     }
1536   }
1537   ierr = MatCreateNest(PetscObjectComm((PetscObject)fine),nDM,NULL,nDM,NULL,mats,A);CHKERRQ(ierr);
1538   if (v) {
1539     ierr = VecCreateNest(PetscObjectComm((PetscObject)fine),nDM,NULL,vecs,v);CHKERRQ(ierr);
1540   }
1541   for (i=0; i<nDM*nDM; i++) {ierr = MatDestroy(&mats[i]);CHKERRQ(ierr);}
1542   ierr = PetscFree(mats);CHKERRQ(ierr);
1543   if (v) {
1544     for (i=0; i<nDM; i++) {ierr = VecDestroy(&vecs[i]);CHKERRQ(ierr);}
1545     ierr = PetscFree(vecs);CHKERRQ(ierr);
1546   }
1547   PetscFunctionReturn(0);
1548 }
1549 
1550 static PetscErrorCode DMGetLocalToGlobalMapping_Composite(DM dm)
1551 {
1552   DM_Composite           *com = (DM_Composite*)dm->data;
1553   ISLocalToGlobalMapping *ltogs;
1554   PetscInt               i;
1555   PetscErrorCode         ierr;
1556 
1557   PetscFunctionBegin;
1558   /* Set the ISLocalToGlobalMapping on the new matrix */
1559   ierr = DMCompositeGetISLocalToGlobalMappings(dm,&ltogs);CHKERRQ(ierr);
1560   ierr = ISLocalToGlobalMappingConcatenate(PetscObjectComm((PetscObject)dm),com->nDM,ltogs,&dm->ltogmap);CHKERRQ(ierr);
1561   for (i=0; i<com->nDM; i++) {ierr = ISLocalToGlobalMappingDestroy(&ltogs[i]);CHKERRQ(ierr);}
1562   ierr = PetscFree(ltogs);CHKERRQ(ierr);
1563   PetscFunctionReturn(0);
1564 }
1565 
1566 
1567 PetscErrorCode  DMCreateColoring_Composite(DM dm,ISColoringType ctype,ISColoring *coloring)
1568 {
1569   PetscErrorCode  ierr;
1570   PetscInt        n,i,cnt;
1571   ISColoringValue *colors;
1572   PetscBool       dense  = PETSC_FALSE;
1573   ISColoringValue maxcol = 0;
1574   DM_Composite    *com   = (DM_Composite*)dm->data;
1575 
1576   PetscFunctionBegin;
1577   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1578   if (ctype == IS_COLORING_LOCAL) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only global coloring supported");
1579   else if (ctype == IS_COLORING_GLOBAL) {
1580     n = com->n;
1581   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Unknown ISColoringType");
1582   ierr = PetscMalloc1(n,&colors);CHKERRQ(ierr); /* freed in ISColoringDestroy() */
1583 
1584   ierr = PetscOptionsGetBool(((PetscObject)dm)->options,((PetscObject)dm)->prefix,"-dmcomposite_dense_jacobian",&dense,NULL);CHKERRQ(ierr);
1585   if (dense) {
1586     for (i=0; i<n; i++) {
1587       colors[i] = (ISColoringValue)(com->rstart + i);
1588     }
1589     maxcol = com->N;
1590   } else {
1591     struct DMCompositeLink *next = com->next;
1592     PetscMPIInt            rank;
1593 
1594     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
1595     cnt  = 0;
1596     while (next) {
1597       ISColoring lcoloring;
1598 
1599       ierr = DMCreateColoring(next->dm,IS_COLORING_GLOBAL,&lcoloring);CHKERRQ(ierr);
1600       for (i=0; i<lcoloring->N; i++) {
1601         colors[cnt++] = maxcol + lcoloring->colors[i];
1602       }
1603       maxcol += lcoloring->n;
1604       ierr    = ISColoringDestroy(&lcoloring);CHKERRQ(ierr);
1605       next    = next->next;
1606     }
1607   }
1608   ierr = ISColoringCreate(PetscObjectComm((PetscObject)dm),maxcol,n,colors,PETSC_OWN_POINTER,coloring);CHKERRQ(ierr);
1609   PetscFunctionReturn(0);
1610 }
1611 
1612 PetscErrorCode  DMGlobalToLocalBegin_Composite(DM dm,Vec gvec,InsertMode mode,Vec lvec)
1613 {
1614   PetscErrorCode         ierr;
1615   struct DMCompositeLink *next;
1616   PetscScalar            *garray,*larray;
1617   DM_Composite           *com = (DM_Composite*)dm->data;
1618 
1619   PetscFunctionBegin;
1620   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1621   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
1622 
1623   if (!com->setup) {
1624     ierr = DMSetUp(dm);CHKERRQ(ierr);
1625   }
1626 
1627   ierr = VecGetArray(gvec,&garray);CHKERRQ(ierr);
1628   ierr = VecGetArray(lvec,&larray);CHKERRQ(ierr);
1629 
1630   /* loop over packed objects, handling one at at time */
1631   next = com->next;
1632   while (next) {
1633     Vec      local,global;
1634     PetscInt N;
1635 
1636     ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
1637     ierr = VecGetLocalSize(global,&N);CHKERRQ(ierr);
1638     ierr = VecPlaceArray(global,garray);CHKERRQ(ierr);
1639     ierr = DMGetLocalVector(next->dm,&local);CHKERRQ(ierr);
1640     ierr = VecPlaceArray(local,larray);CHKERRQ(ierr);
1641     ierr = DMGlobalToLocalBegin(next->dm,global,mode,local);CHKERRQ(ierr);
1642     ierr = DMGlobalToLocalEnd(next->dm,global,mode,local);CHKERRQ(ierr);
1643     ierr = VecResetArray(global);CHKERRQ(ierr);
1644     ierr = VecResetArray(local);CHKERRQ(ierr);
1645     ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
1646     ierr = DMRestoreLocalVector(next->dm,&local);CHKERRQ(ierr);
1647 
1648     larray += next->nlocal;
1649     garray += next->n;
1650     next    = next->next;
1651   }
1652 
1653   ierr = VecRestoreArray(gvec,NULL);CHKERRQ(ierr);
1654   ierr = VecRestoreArray(lvec,NULL);CHKERRQ(ierr);
1655   PetscFunctionReturn(0);
1656 }
1657 
1658 PetscErrorCode  DMGlobalToLocalEnd_Composite(DM dm,Vec gvec,InsertMode mode,Vec lvec)
1659 {
1660   PetscFunctionBegin;
1661   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1662   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
1663   PetscValidHeaderSpecific(lvec,VEC_CLASSID,4);
1664   PetscFunctionReturn(0);
1665 }
1666 
1667 PetscErrorCode  DMLocalToGlobalBegin_Composite(DM dm,Vec lvec,InsertMode mode,Vec gvec)
1668 {
1669   PetscErrorCode         ierr;
1670   struct DMCompositeLink *next;
1671   PetscScalar            *larray,*garray;
1672   DM_Composite           *com = (DM_Composite*)dm->data;
1673 
1674   PetscFunctionBegin;
1675   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1676   PetscValidHeaderSpecific(lvec,VEC_CLASSID,2);
1677   PetscValidHeaderSpecific(gvec,VEC_CLASSID,4);
1678 
1679   if (!com->setup) {
1680     ierr = DMSetUp(dm);CHKERRQ(ierr);
1681   }
1682 
1683   ierr = VecGetArray(lvec,&larray);CHKERRQ(ierr);
1684   ierr = VecGetArray(gvec,&garray);CHKERRQ(ierr);
1685 
1686   /* loop over packed objects, handling one at at time */
1687   next = com->next;
1688   while (next) {
1689     Vec      global,local;
1690 
1691     ierr = DMGetLocalVector(next->dm,&local);CHKERRQ(ierr);
1692     ierr = VecPlaceArray(local,larray);CHKERRQ(ierr);
1693     ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
1694     ierr = VecPlaceArray(global,garray);CHKERRQ(ierr);
1695     ierr = DMLocalToGlobalBegin(next->dm,local,mode,global);CHKERRQ(ierr);
1696     ierr = DMLocalToGlobalEnd(next->dm,local,mode,global);CHKERRQ(ierr);
1697     ierr = VecResetArray(local);CHKERRQ(ierr);
1698     ierr = VecResetArray(global);CHKERRQ(ierr);
1699     ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
1700     ierr = DMRestoreLocalVector(next->dm,&local);CHKERRQ(ierr);
1701 
1702     garray += next->n;
1703     larray += next->nlocal;
1704     next    = next->next;
1705   }
1706 
1707   ierr = VecRestoreArray(gvec,NULL);CHKERRQ(ierr);
1708   ierr = VecRestoreArray(lvec,NULL);CHKERRQ(ierr);
1709 
1710   PetscFunctionReturn(0);
1711 }
1712 
1713 PetscErrorCode  DMLocalToGlobalEnd_Composite(DM dm,Vec lvec,InsertMode mode,Vec gvec)
1714 {
1715   PetscFunctionBegin;
1716   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1717   PetscValidHeaderSpecific(lvec,VEC_CLASSID,2);
1718   PetscValidHeaderSpecific(gvec,VEC_CLASSID,4);
1719   PetscFunctionReturn(0);
1720 }
1721 
1722 PetscErrorCode  DMLocalToLocalBegin_Composite(DM dm,Vec vec1,InsertMode mode,Vec vec2)
1723 {
1724   PetscErrorCode         ierr;
1725   struct DMCompositeLink *next;
1726   PetscScalar            *array1,*array2;
1727   DM_Composite           *com = (DM_Composite*)dm->data;
1728 
1729   PetscFunctionBegin;
1730   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1731   PetscValidHeaderSpecific(vec1,VEC_CLASSID,2);
1732   PetscValidHeaderSpecific(vec2,VEC_CLASSID,4);
1733 
1734   if (!com->setup) {
1735     ierr = DMSetUp(dm);CHKERRQ(ierr);
1736   }
1737 
1738   ierr = VecGetArray(vec1,&array1);CHKERRQ(ierr);
1739   ierr = VecGetArray(vec2,&array2);CHKERRQ(ierr);
1740 
1741   /* loop over packed objects, handling one at at time */
1742   next = com->next;
1743   while (next) {
1744     Vec      local1,local2;
1745 
1746     ierr = DMGetLocalVector(next->dm,&local1);CHKERRQ(ierr);
1747     ierr = VecPlaceArray(local1,array1);CHKERRQ(ierr);
1748     ierr = DMGetLocalVector(next->dm,&local2);CHKERRQ(ierr);
1749     ierr = VecPlaceArray(local2,array2);CHKERRQ(ierr);
1750     ierr = DMLocalToLocalBegin(next->dm,local1,mode,local2);CHKERRQ(ierr);
1751     ierr = DMLocalToLocalEnd(next->dm,local1,mode,local2);CHKERRQ(ierr);
1752     ierr = VecResetArray(local2);CHKERRQ(ierr);
1753     ierr = DMRestoreLocalVector(next->dm,&local2);CHKERRQ(ierr);
1754     ierr = VecResetArray(local1);CHKERRQ(ierr);
1755     ierr = DMRestoreLocalVector(next->dm,&local1);CHKERRQ(ierr);
1756 
1757     array1 += next->nlocal;
1758     array2 += next->nlocal;
1759     next    = next->next;
1760   }
1761 
1762   ierr = VecRestoreArray(vec1,NULL);CHKERRQ(ierr);
1763   ierr = VecRestoreArray(vec2,NULL);CHKERRQ(ierr);
1764 
1765   PetscFunctionReturn(0);
1766 }
1767 
1768 PetscErrorCode  DMLocalToLocalEnd_Composite(DM dm,Vec lvec,InsertMode mode,Vec gvec)
1769 {
1770   PetscFunctionBegin;
1771   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1772   PetscValidHeaderSpecific(lvec,VEC_CLASSID,2);
1773   PetscValidHeaderSpecific(gvec,VEC_CLASSID,4);
1774   PetscFunctionReturn(0);
1775 }
1776 
1777 /*MC
1778    DMCOMPOSITE = "composite" - A DM object that is used to manage data for a collection of DMs
1779 
1780   Level: intermediate
1781 
1782 .seealso: DMType, DM, DMDACreate(), DMCreate(), DMSetType(), DMCompositeCreate()
1783 M*/
1784 
1785 
1786 PETSC_EXTERN PetscErrorCode DMCreate_Composite(DM p)
1787 {
1788   PetscErrorCode ierr;
1789   DM_Composite   *com;
1790 
1791   PetscFunctionBegin;
1792   ierr          = PetscNewLog(p,&com);CHKERRQ(ierr);
1793   p->data       = com;
1794   ierr          = PetscObjectChangeTypeName((PetscObject)p,"DMComposite");CHKERRQ(ierr);
1795   com->n        = 0;
1796   com->nghost   = 0;
1797   com->next     = NULL;
1798   com->nDM      = 0;
1799 
1800   p->ops->createglobalvector              = DMCreateGlobalVector_Composite;
1801   p->ops->createlocalvector               = DMCreateLocalVector_Composite;
1802   p->ops->getlocaltoglobalmapping         = DMGetLocalToGlobalMapping_Composite;
1803   p->ops->createfieldis                   = DMCreateFieldIS_Composite;
1804   p->ops->createfielddecomposition        = DMCreateFieldDecomposition_Composite;
1805   p->ops->refine                          = DMRefine_Composite;
1806   p->ops->coarsen                         = DMCoarsen_Composite;
1807   p->ops->createinterpolation             = DMCreateInterpolation_Composite;
1808   p->ops->creatematrix                    = DMCreateMatrix_Composite;
1809   p->ops->getcoloring                     = DMCreateColoring_Composite;
1810   p->ops->globaltolocalbegin              = DMGlobalToLocalBegin_Composite;
1811   p->ops->globaltolocalend                = DMGlobalToLocalEnd_Composite;
1812   p->ops->localtoglobalbegin              = DMLocalToGlobalBegin_Composite;
1813   p->ops->localtoglobalend                = DMLocalToGlobalEnd_Composite;
1814   p->ops->localtolocalbegin               = DMLocalToLocalBegin_Composite;
1815   p->ops->localtolocalend                 = DMLocalToLocalEnd_Composite;
1816   p->ops->destroy                         = DMDestroy_Composite;
1817   p->ops->view                            = DMView_Composite;
1818   p->ops->setup                           = DMSetUp_Composite;
1819 
1820   ierr = PetscObjectComposeFunction((PetscObject)p,"DMSetUpGLVisViewer_C",DMSetUpGLVisViewer_Composite);CHKERRQ(ierr);
1821   PetscFunctionReturn(0);
1822 }
1823 
1824 /*@
1825     DMCompositeCreate - Creates a vector packer, used to generate "composite"
1826       vectors made up of several subvectors.
1827 
1828     Collective on MPI_Comm
1829 
1830     Input Parameter:
1831 .   comm - the processors that will share the global vector
1832 
1833     Output Parameters:
1834 .   packer - the packer object
1835 
1836     Level: advanced
1837 
1838 .seealso DMDestroy(), DMCompositeAddDM(), DMCompositeScatter(), DMCOMPOSITE,DMCreate()
1839          DMCompositeGather(), DMCreateGlobalVector(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess()
1840          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
1841 
1842 @*/
1843 PetscErrorCode  DMCompositeCreate(MPI_Comm comm,DM *packer)
1844 {
1845   PetscErrorCode ierr;
1846 
1847   PetscFunctionBegin;
1848   PetscValidPointer(packer,2);
1849   ierr = DMCreate(comm,packer);CHKERRQ(ierr);
1850   ierr = DMSetType(*packer,DMCOMPOSITE);CHKERRQ(ierr);
1851   PetscFunctionReturn(0);
1852 }
1853