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