xref: /petsc/src/dm/impls/composite/pack.c (revision bebe2cf65d55febe21a5af8db2bd2e168caaa2e7)
147c6ae99SBarry Smith 
2ccd284c7SBarry Smith #include <../src/dm/impls/composite/packimpl.h>       /*I  "petscdmcomposite.h"  I*/
3af0996ceSBarry Smith #include <petsc/private/isimpl.h>
42764a2aaSMatthew G. Knepley #include <petscds.h>
547c6ae99SBarry Smith 
647c6ae99SBarry Smith #undef __FUNCT__
747c6ae99SBarry Smith #define __FUNCT__ "DMCompositeSetCoupling"
847c6ae99SBarry Smith /*@C
947c6ae99SBarry Smith     DMCompositeSetCoupling - Sets user provided routines that compute the coupling between the
10*bebe2cf6SSatish Balay       separate components (DMs) in a DMto build the correct matrix nonzero structure.
1147c6ae99SBarry Smith 
1247c6ae99SBarry Smith 
1347c6ae99SBarry Smith     Logically Collective on MPI_Comm
1447c6ae99SBarry Smith 
1547c6ae99SBarry Smith     Input Parameter:
1647c6ae99SBarry Smith +   dm - the composite object
1747c6ae99SBarry Smith -   formcouplelocations - routine to set the nonzero locations in the matrix
1847c6ae99SBarry Smith 
1947c6ae99SBarry Smith     Level: advanced
2047c6ae99SBarry Smith 
211b2093e4SBarry Smith     Notes: See DMSetApplicationContext() and DMGetApplicationContext() for how to get user information into
2247c6ae99SBarry Smith         this routine
2347c6ae99SBarry Smith 
2447c6ae99SBarry Smith @*/
257087cfbeSBarry Smith PetscErrorCode  DMCompositeSetCoupling(DM dm,PetscErrorCode (*FormCoupleLocations)(DM,Mat,PetscInt*,PetscInt*,PetscInt,PetscInt,PetscInt,PetscInt))
2647c6ae99SBarry Smith {
2747c6ae99SBarry Smith   DM_Composite *com = (DM_Composite*)dm->data;
2847c6ae99SBarry Smith 
2947c6ae99SBarry Smith   PetscFunctionBegin;
3047c6ae99SBarry Smith   com->FormCoupleLocations = FormCoupleLocations;
3147c6ae99SBarry Smith   PetscFunctionReturn(0);
3247c6ae99SBarry Smith }
3347c6ae99SBarry Smith 
3447c6ae99SBarry Smith #undef __FUNCT__
350c010503SBarry Smith #define __FUNCT__ "DMDestroy_Composite"
366bf464f9SBarry Smith PetscErrorCode  DMDestroy_Composite(DM dm)
3747c6ae99SBarry Smith {
3847c6ae99SBarry Smith   PetscErrorCode         ierr;
3947c6ae99SBarry Smith   struct DMCompositeLink *next, *prev;
4047c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
4147c6ae99SBarry Smith 
4247c6ae99SBarry Smith   PetscFunctionBegin;
4347c6ae99SBarry Smith   next = com->next;
4447c6ae99SBarry Smith   while (next) {
4547c6ae99SBarry Smith     prev = next;
4647c6ae99SBarry Smith     next = next->next;
47fcfd50ebSBarry Smith     ierr = DMDestroy(&prev->dm);CHKERRQ(ierr);
4847c6ae99SBarry Smith     ierr = PetscFree(prev->grstarts);CHKERRQ(ierr);
4947c6ae99SBarry Smith     ierr = PetscFree(prev);CHKERRQ(ierr);
5047c6ae99SBarry Smith   }
51435a35e8SMatthew G Knepley   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
52435a35e8SMatthew G Knepley   ierr = PetscFree(com);CHKERRQ(ierr);
5347c6ae99SBarry Smith   PetscFunctionReturn(0);
5447c6ae99SBarry Smith }
5547c6ae99SBarry Smith 
5647c6ae99SBarry Smith #undef __FUNCT__
570c010503SBarry Smith #define __FUNCT__ "DMView_Composite"
587087cfbeSBarry Smith PetscErrorCode  DMView_Composite(DM dm,PetscViewer v)
5947c6ae99SBarry Smith {
6047c6ae99SBarry Smith   PetscErrorCode ierr;
6147c6ae99SBarry Smith   PetscBool      iascii;
6247c6ae99SBarry Smith   DM_Composite   *com = (DM_Composite*)dm->data;
6347c6ae99SBarry Smith 
6447c6ae99SBarry Smith   PetscFunctionBegin;
65251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
6647c6ae99SBarry Smith   if (iascii) {
6747c6ae99SBarry Smith     struct DMCompositeLink *lnk = com->next;
6847c6ae99SBarry Smith     PetscInt               i;
6947c6ae99SBarry Smith 
7047c6ae99SBarry Smith     ierr = PetscViewerASCIIPrintf(v,"DM (%s)\n",((PetscObject)dm)->prefix ? ((PetscObject)dm)->prefix : "no prefix");CHKERRQ(ierr);
719ae5db72SJed Brown     ierr = PetscViewerASCIIPrintf(v,"  contains %D DMs\n",com->nDM);CHKERRQ(ierr);
7247c6ae99SBarry Smith     ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr);
7347c6ae99SBarry Smith     for (i=0; lnk; lnk=lnk->next,i++) {
749ae5db72SJed Brown       ierr = PetscViewerASCIIPrintf(v,"Link %D: DM of type %s\n",i,((PetscObject)lnk->dm)->type_name);CHKERRQ(ierr);
7547c6ae99SBarry Smith       ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr);
7647c6ae99SBarry Smith       ierr = DMView(lnk->dm,v);CHKERRQ(ierr);
7747c6ae99SBarry Smith       ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr);
7847c6ae99SBarry Smith     }
7947c6ae99SBarry Smith     ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr);
8047c6ae99SBarry Smith   }
8147c6ae99SBarry Smith   PetscFunctionReturn(0);
8247c6ae99SBarry Smith }
8347c6ae99SBarry Smith 
8447c6ae99SBarry Smith /* --------------------------------------------------------------------------------------*/
8547c6ae99SBarry Smith #undef __FUNCT__
86d7bf68aeSBarry Smith #define __FUNCT__ "DMSetUp_Composite"
877087cfbeSBarry Smith PetscErrorCode  DMSetUp_Composite(DM dm)
8847c6ae99SBarry Smith {
8947c6ae99SBarry Smith   PetscErrorCode         ierr;
9047c6ae99SBarry Smith   PetscInt               nprev = 0;
9147c6ae99SBarry Smith   PetscMPIInt            rank,size;
9247c6ae99SBarry Smith   DM_Composite           *com  = (DM_Composite*)dm->data;
9347c6ae99SBarry Smith   struct DMCompositeLink *next = com->next;
9447c6ae99SBarry Smith   PetscLayout            map;
9547c6ae99SBarry Smith 
9647c6ae99SBarry Smith   PetscFunctionBegin;
97ce94432eSBarry Smith   if (com->setup) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Packer has already been setup");
98ce94432eSBarry Smith   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)dm),&map);CHKERRQ(ierr);
9947c6ae99SBarry Smith   ierr = PetscLayoutSetLocalSize(map,com->n);CHKERRQ(ierr);
10047c6ae99SBarry Smith   ierr = PetscLayoutSetSize(map,PETSC_DETERMINE);CHKERRQ(ierr);
10147c6ae99SBarry Smith   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
10247c6ae99SBarry Smith   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
10347c6ae99SBarry Smith   ierr = PetscLayoutGetSize(map,&com->N);CHKERRQ(ierr);
1040298fd71SBarry Smith   ierr = PetscLayoutGetRange(map,&com->rstart,NULL);CHKERRQ(ierr);
105fcfd50ebSBarry Smith   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
10647c6ae99SBarry Smith 
1079ae5db72SJed Brown   /* now set the rstart for each linked vector */
108ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
109ce94432eSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm),&size);CHKERRQ(ierr);
11047c6ae99SBarry Smith   while (next) {
11147c6ae99SBarry Smith     next->rstart  = nprev;
11206ebdd98SJed Brown     nprev        += next->n;
11347c6ae99SBarry Smith     next->grstart = com->rstart + next->rstart;
114785e854fSJed Brown     ierr          = PetscMalloc1(size,&next->grstarts);CHKERRQ(ierr);
115ce94432eSBarry Smith     ierr          = MPI_Allgather(&next->grstart,1,MPIU_INT,next->grstarts,1,MPIU_INT,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
11647c6ae99SBarry Smith     next          = next->next;
11747c6ae99SBarry Smith   }
11847c6ae99SBarry Smith   com->setup = PETSC_TRUE;
11947c6ae99SBarry Smith   PetscFunctionReturn(0);
12047c6ae99SBarry Smith }
12147c6ae99SBarry Smith 
12247c6ae99SBarry Smith /* ----------------------------------------------------------------------------------*/
12347c6ae99SBarry Smith 
12447c6ae99SBarry Smith #undef __FUNCT__
12547c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetNumberDM"
12673e31fe2SJed Brown /*@
12747c6ae99SBarry Smith     DMCompositeGetNumberDM - Get's the number of DM objects in the DMComposite
12847c6ae99SBarry Smith        representation.
12947c6ae99SBarry Smith 
13047c6ae99SBarry Smith     Not Collective
13147c6ae99SBarry Smith 
13247c6ae99SBarry Smith     Input Parameter:
13347c6ae99SBarry Smith .    dm - the packer object
13447c6ae99SBarry Smith 
13547c6ae99SBarry Smith     Output Parameter:
13647c6ae99SBarry Smith .     nDM - the number of DMs
13747c6ae99SBarry Smith 
13847c6ae99SBarry Smith     Level: beginner
13947c6ae99SBarry Smith 
14047c6ae99SBarry Smith @*/
1417087cfbeSBarry Smith PetscErrorCode  DMCompositeGetNumberDM(DM dm,PetscInt *nDM)
14247c6ae99SBarry Smith {
14347c6ae99SBarry Smith   DM_Composite *com = (DM_Composite*)dm->data;
1445fd66863SKarl Rupp 
14547c6ae99SBarry Smith   PetscFunctionBegin;
14647c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
14747c6ae99SBarry Smith   *nDM = com->nDM;
14847c6ae99SBarry Smith   PetscFunctionReturn(0);
14947c6ae99SBarry Smith }
15047c6ae99SBarry Smith 
15147c6ae99SBarry Smith 
15247c6ae99SBarry Smith #undef __FUNCT__
15347c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetAccess"
15447c6ae99SBarry Smith /*@C
15547c6ae99SBarry Smith     DMCompositeGetAccess - Allows one to access the individual packed vectors in their global
15647c6ae99SBarry Smith        representation.
15747c6ae99SBarry Smith 
15847c6ae99SBarry Smith     Collective on DMComposite
15947c6ae99SBarry Smith 
1609ae5db72SJed Brown     Input Parameters:
16147c6ae99SBarry Smith +    dm - the packer object
1629ae5db72SJed Brown -    gvec - the global vector
1639ae5db72SJed Brown 
1649ae5db72SJed Brown     Output Parameters:
1650298fd71SBarry Smith .    Vec* ... - the packed parallel vectors, NULL for those that are not needed
16647c6ae99SBarry Smith 
16747c6ae99SBarry Smith     Notes: Use DMCompositeRestoreAccess() to return the vectors when you no longer need them
16847c6ae99SBarry Smith 
169f73e5cebSJed Brown     Fortran Notes:
170f73e5cebSJed Brown 
171f73e5cebSJed Brown     Fortran callers must use numbered versions of this routine, e.g., DMCompositeGetAccess4(dm,gvec,vec1,vec2,vec3,vec4)
172f73e5cebSJed Brown     or use the alternative interface DMCompositeGetAccessArray().
173f73e5cebSJed Brown 
17447c6ae99SBarry Smith     Level: advanced
17547c6ae99SBarry Smith 
176f73e5cebSJed Brown .seealso: DMCompositeGetEntries(), DMCompositeScatter()
17747c6ae99SBarry Smith @*/
1787087cfbeSBarry Smith PetscErrorCode  DMCompositeGetAccess(DM dm,Vec gvec,...)
17947c6ae99SBarry Smith {
18047c6ae99SBarry Smith   va_list                Argp;
18147c6ae99SBarry Smith   PetscErrorCode         ierr;
18247c6ae99SBarry Smith   struct DMCompositeLink *next;
18347c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
1845edff71fSBarry Smith   PetscInt               readonly;
18547c6ae99SBarry Smith 
18647c6ae99SBarry Smith   PetscFunctionBegin;
18747c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
18847c6ae99SBarry Smith   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
18947c6ae99SBarry Smith   next = com->next;
19047c6ae99SBarry Smith   if (!com->setup) {
191d7bf68aeSBarry Smith     ierr = DMSetUp(dm);CHKERRQ(ierr);
19247c6ae99SBarry Smith   }
19347c6ae99SBarry Smith 
1945edff71fSBarry Smith   ierr = VecLockGet(gvec,&readonly);CHKERRQ(ierr);
19547c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
19647c6ae99SBarry Smith   va_start(Argp,gvec);
19747c6ae99SBarry Smith   while (next) {
19847c6ae99SBarry Smith     Vec *vec;
19947c6ae99SBarry Smith     vec = va_arg(Argp, Vec*);
2009ae5db72SJed Brown     if (vec) {
2019ae5db72SJed Brown       ierr = DMGetGlobalVector(next->dm,vec);CHKERRQ(ierr);
2025edff71fSBarry Smith       if (readonly) {
2035edff71fSBarry Smith         const PetscScalar *array;
2045edff71fSBarry Smith         ierr = VecGetArrayRead(gvec,&array);CHKERRQ(ierr);
2055edff71fSBarry Smith         ierr = VecPlaceArray(*vec,array+next->rstart);CHKERRQ(ierr);
2065edff71fSBarry Smith         ierr = VecLockPush(*vec);CHKERRQ(ierr);
2075edff71fSBarry Smith         ierr = VecRestoreArrayRead(gvec,&array);CHKERRQ(ierr);
2085edff71fSBarry Smith       } else {
2095edff71fSBarry Smith         PetscScalar *array;
2109ae5db72SJed Brown         ierr = VecGetArray(gvec,&array);CHKERRQ(ierr);
2119ae5db72SJed Brown         ierr = VecPlaceArray(*vec,array+next->rstart);CHKERRQ(ierr);
2129ae5db72SJed Brown         ierr = VecRestoreArray(gvec,&array);CHKERRQ(ierr);
21347c6ae99SBarry Smith       }
2145edff71fSBarry Smith     }
21547c6ae99SBarry Smith     next = next->next;
21647c6ae99SBarry Smith   }
21747c6ae99SBarry Smith   va_end(Argp);
21847c6ae99SBarry Smith   PetscFunctionReturn(0);
21947c6ae99SBarry Smith }
22047c6ae99SBarry Smith 
22147c6ae99SBarry Smith #undef __FUNCT__
222f73e5cebSJed Brown #define __FUNCT__ "DMCompositeGetAccessArray"
223f73e5cebSJed Brown /*@C
224f73e5cebSJed Brown     DMCompositeGetAccessArray - Allows one to access the individual packed vectors in their global
225f73e5cebSJed Brown        representation.
226f73e5cebSJed Brown 
227f73e5cebSJed Brown     Collective on DMComposite
228f73e5cebSJed Brown 
229f73e5cebSJed Brown     Input Parameters:
230f73e5cebSJed Brown +    dm - the packer object
231f73e5cebSJed Brown .    pvec - packed vector
232f73e5cebSJed Brown .    nwanted - number of vectors wanted
2330298fd71SBarry Smith -    wanted - sorted array of vectors wanted, or NULL to get all vectors
234f73e5cebSJed Brown 
235f73e5cebSJed Brown     Output Parameters:
236f73e5cebSJed Brown .    vecs - array of requested global vectors (must be allocated)
237f73e5cebSJed Brown 
238f73e5cebSJed Brown     Notes: Use DMCompositeRestoreAccessArray() to return the vectors when you no longer need them
239f73e5cebSJed Brown 
240f73e5cebSJed Brown     Level: advanced
241f73e5cebSJed Brown 
242f73e5cebSJed Brown .seealso: DMCompositeGetAccess(), DMCompositeGetEntries(), DMCompositeScatter(), DMCompositeGather()
243f73e5cebSJed Brown @*/
244f73e5cebSJed Brown PetscErrorCode  DMCompositeGetAccessArray(DM dm,Vec pvec,PetscInt nwanted,const PetscInt *wanted,Vec *vecs)
245f73e5cebSJed Brown {
246f73e5cebSJed Brown   PetscErrorCode         ierr;
247f73e5cebSJed Brown   struct DMCompositeLink *link;
248f73e5cebSJed Brown   PetscInt               i,wnum;
249f73e5cebSJed Brown   DM_Composite           *com = (DM_Composite*)dm->data;
250bee642f7SBarry Smith   PetscInt               readonly;
251f73e5cebSJed Brown 
252f73e5cebSJed Brown   PetscFunctionBegin;
253f73e5cebSJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
254f73e5cebSJed Brown   PetscValidHeaderSpecific(pvec,VEC_CLASSID,2);
255f73e5cebSJed Brown   if (!com->setup) {
256f73e5cebSJed Brown     ierr = DMSetUp(dm);CHKERRQ(ierr);
257f73e5cebSJed Brown   }
258f73e5cebSJed Brown 
259bee642f7SBarry Smith   ierr = VecLockGet(pvec,&readonly);CHKERRQ(ierr);
260f73e5cebSJed Brown   for (i=0,wnum=0,link=com->next; link && wnum<nwanted; i++,link=link->next) {
261f73e5cebSJed Brown     if (!wanted || i == wanted[wnum]) {
262f73e5cebSJed Brown       Vec v;
263f73e5cebSJed Brown       ierr = DMGetGlobalVector(link->dm,&v);CHKERRQ(ierr);
264bee642f7SBarry Smith       if (readonly) {
265bee642f7SBarry Smith         const PetscScalar *array;
266bee642f7SBarry Smith         ierr = VecGetArrayRead(pvec,&array);CHKERRQ(ierr);
267bee642f7SBarry Smith         ierr = VecPlaceArray(v,array+link->rstart);CHKERRQ(ierr);
268bee642f7SBarry Smith         ierr = VecLockPush(v);CHKERRQ(ierr);
269bee642f7SBarry Smith         ierr = VecRestoreArrayRead(pvec,&array);CHKERRQ(ierr);
270bee642f7SBarry Smith       } else {
271bee642f7SBarry Smith         PetscScalar *array;
272f73e5cebSJed Brown         ierr = VecGetArray(pvec,&array);CHKERRQ(ierr);
273f73e5cebSJed Brown         ierr = VecPlaceArray(v,array+link->rstart);CHKERRQ(ierr);
274f73e5cebSJed Brown         ierr = VecRestoreArray(pvec,&array);CHKERRQ(ierr);
275bee642f7SBarry Smith       }
276f73e5cebSJed Brown       vecs[wnum++] = v;
277f73e5cebSJed Brown     }
278f73e5cebSJed Brown   }
279f73e5cebSJed Brown   PetscFunctionReturn(0);
280f73e5cebSJed Brown }
281f73e5cebSJed Brown 
282f73e5cebSJed Brown #undef __FUNCT__
28347c6ae99SBarry Smith #define __FUNCT__ "DMCompositeRestoreAccess"
28447c6ae99SBarry Smith /*@C
285aa219208SBarry Smith     DMCompositeRestoreAccess - Returns the vectors obtained with DMCompositeGetAccess()
28647c6ae99SBarry Smith        representation.
28747c6ae99SBarry Smith 
28847c6ae99SBarry Smith     Collective on DMComposite
28947c6ae99SBarry Smith 
2909ae5db72SJed Brown     Input Parameters:
29147c6ae99SBarry Smith +    dm - the packer object
29247c6ae99SBarry Smith .    gvec - the global vector
2930298fd71SBarry Smith -    Vec* ... - the individual parallel vectors, NULL for those that are not needed
29447c6ae99SBarry Smith 
29547c6ae99SBarry Smith     Level: advanced
29647c6ae99SBarry Smith 
2979ae5db72SJed Brown .seealso  DMCompositeAddDM(), DMCreateGlobalVector(),
2986eb61c8cSJed Brown          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeScatter(),
299aa219208SBarry Smith          DMCompositeRestoreAccess(), DMCompositeGetAccess()
30047c6ae99SBarry Smith 
30147c6ae99SBarry Smith @*/
3027087cfbeSBarry Smith PetscErrorCode  DMCompositeRestoreAccess(DM dm,Vec gvec,...)
30347c6ae99SBarry Smith {
30447c6ae99SBarry Smith   va_list                Argp;
30547c6ae99SBarry Smith   PetscErrorCode         ierr;
30647c6ae99SBarry Smith   struct DMCompositeLink *next;
30747c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
3085edff71fSBarry Smith   PetscInt               readonly;
30947c6ae99SBarry Smith 
31047c6ae99SBarry Smith   PetscFunctionBegin;
31147c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
31247c6ae99SBarry Smith   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
31347c6ae99SBarry Smith   next = com->next;
31447c6ae99SBarry Smith   if (!com->setup) {
315d7bf68aeSBarry Smith     ierr = DMSetUp(dm);CHKERRQ(ierr);
31647c6ae99SBarry Smith   }
31747c6ae99SBarry Smith 
3185edff71fSBarry Smith   ierr = VecLockGet(gvec,&readonly);CHKERRQ(ierr);
31947c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
32047c6ae99SBarry Smith   va_start(Argp,gvec);
32147c6ae99SBarry Smith   while (next) {
32247c6ae99SBarry Smith     Vec *vec;
32347c6ae99SBarry Smith     vec = va_arg(Argp, Vec*);
3249ae5db72SJed Brown     if (vec) {
3259ae5db72SJed Brown       ierr = VecResetArray(*vec);CHKERRQ(ierr);
3265edff71fSBarry Smith       if (readonly) {
3275edff71fSBarry Smith         ierr = VecLockPop(*vec);CHKERRQ(ierr);
3285edff71fSBarry Smith       }
329bee642f7SBarry Smith       ierr = DMRestoreGlobalVector(next->dm,vec);CHKERRQ(ierr);
33047c6ae99SBarry Smith     }
33147c6ae99SBarry Smith     next = next->next;
33247c6ae99SBarry Smith   }
33347c6ae99SBarry Smith   va_end(Argp);
33447c6ae99SBarry Smith   PetscFunctionReturn(0);
33547c6ae99SBarry Smith }
33647c6ae99SBarry Smith 
33747c6ae99SBarry Smith #undef __FUNCT__
338f73e5cebSJed Brown #define __FUNCT__ "DMCompositeRestoreAccessArray"
339f73e5cebSJed Brown /*@C
340f73e5cebSJed Brown     DMCompositeRestoreAccessArray - Returns the vectors obtained with DMCompositeGetAccessArray()
341f73e5cebSJed Brown 
342f73e5cebSJed Brown     Collective on DMComposite
343f73e5cebSJed Brown 
344f73e5cebSJed Brown     Input Parameters:
345f73e5cebSJed Brown +    dm - the packer object
346f73e5cebSJed Brown .    pvec - packed vector
347f73e5cebSJed Brown .    nwanted - number of vectors wanted
3480298fd71SBarry Smith .    wanted - sorted array of vectors wanted, or NULL to get all vectors
349f73e5cebSJed Brown -    vecs - array of global vectors to return
350f73e5cebSJed Brown 
351f73e5cebSJed Brown     Level: advanced
352f73e5cebSJed Brown 
353f73e5cebSJed Brown .seealso: DMCompositeRestoreAccess(), DMCompositeRestoreEntries(), DMCompositeScatter(), DMCompositeGather()
354f73e5cebSJed Brown @*/
355f73e5cebSJed Brown PetscErrorCode  DMCompositeRestoreAccessArray(DM dm,Vec pvec,PetscInt nwanted,const PetscInt *wanted,Vec *vecs)
356f73e5cebSJed Brown {
357f73e5cebSJed Brown   PetscErrorCode         ierr;
358f73e5cebSJed Brown   struct DMCompositeLink *link;
359f73e5cebSJed Brown   PetscInt               i,wnum;
360f73e5cebSJed Brown   DM_Composite           *com = (DM_Composite*)dm->data;
361bee642f7SBarry Smith   PetscInt               readonly;
362f73e5cebSJed Brown 
363f73e5cebSJed Brown   PetscFunctionBegin;
364f73e5cebSJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
365f73e5cebSJed Brown   PetscValidHeaderSpecific(pvec,VEC_CLASSID,2);
366f73e5cebSJed Brown   if (!com->setup) {
367f73e5cebSJed Brown     ierr = DMSetUp(dm);CHKERRQ(ierr);
368f73e5cebSJed Brown   }
369f73e5cebSJed Brown 
370bee642f7SBarry Smith   ierr = VecLockGet(pvec,&readonly);CHKERRQ(ierr);
371f73e5cebSJed Brown   for (i=0,wnum=0,link=com->next; link && wnum<nwanted; i++,link=link->next) {
372f73e5cebSJed Brown     if (!wanted || i == wanted[wnum]) {
373f73e5cebSJed Brown       ierr = VecResetArray(vecs[wnum]);CHKERRQ(ierr);
374bee642f7SBarry Smith       if (readonly) {
375bee642f7SBarry Smith         ierr = VecLockPop(vecs[wnum]);CHKERRQ(ierr);
376bee642f7SBarry Smith       }
377f73e5cebSJed Brown       ierr = DMRestoreGlobalVector(link->dm,&vecs[wnum]);CHKERRQ(ierr);
378f73e5cebSJed Brown       wnum++;
379f73e5cebSJed Brown     }
380f73e5cebSJed Brown   }
381f73e5cebSJed Brown   PetscFunctionReturn(0);
382f73e5cebSJed Brown }
383f73e5cebSJed Brown 
384f73e5cebSJed Brown #undef __FUNCT__
38547c6ae99SBarry Smith #define __FUNCT__ "DMCompositeScatter"
38647c6ae99SBarry Smith /*@C
38747c6ae99SBarry Smith     DMCompositeScatter - Scatters from a global packed vector into its individual local vectors
38847c6ae99SBarry Smith 
38947c6ae99SBarry Smith     Collective on DMComposite
39047c6ae99SBarry Smith 
3919ae5db72SJed Brown     Input Parameters:
39247c6ae99SBarry Smith +    dm - the packer object
39347c6ae99SBarry Smith .    gvec - the global vector
3940298fd71SBarry Smith -    Vec ... - the individual sequential vectors, NULL for those that are not needed
39547c6ae99SBarry Smith 
39647c6ae99SBarry Smith     Level: advanced
39747c6ae99SBarry Smith 
3986f3c3dcfSJed Brown     Notes:
3996f3c3dcfSJed Brown     DMCompositeScatterArray() is a non-variadic alternative that is often more convenient for library callers and is
4006f3c3dcfSJed Brown     accessible from Fortran.
4016f3c3dcfSJed Brown 
4029ae5db72SJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
4036eb61c8cSJed Brown          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
40447c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
4056f3c3dcfSJed Brown          DMCompositeScatterArray()
40647c6ae99SBarry Smith 
40747c6ae99SBarry Smith @*/
4087087cfbeSBarry Smith PetscErrorCode  DMCompositeScatter(DM dm,Vec gvec,...)
40947c6ae99SBarry Smith {
41047c6ae99SBarry Smith   va_list                Argp;
41147c6ae99SBarry Smith   PetscErrorCode         ierr;
41247c6ae99SBarry Smith   struct DMCompositeLink *next;
4138fd8f222SJed Brown   PetscInt               cnt;
41447c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
41547c6ae99SBarry Smith 
41647c6ae99SBarry Smith   PetscFunctionBegin;
41747c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
41847c6ae99SBarry Smith   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
41947c6ae99SBarry Smith   if (!com->setup) {
420d7bf68aeSBarry Smith     ierr = DMSetUp(dm);CHKERRQ(ierr);
42147c6ae99SBarry Smith   }
42247c6ae99SBarry Smith 
42347c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
42447c6ae99SBarry Smith   va_start(Argp,gvec);
4258fd8f222SJed Brown   for (cnt=3,next=com->next; next; cnt++,next=next->next) {
4269ae5db72SJed Brown     Vec local;
4279ae5db72SJed Brown     local = va_arg(Argp, Vec);
4289ae5db72SJed Brown     if (local) {
4299ae5db72SJed Brown       Vec               global;
4305edff71fSBarry Smith       const PetscScalar *array;
4319ae5db72SJed Brown       PetscValidHeaderSpecific(local,VEC_CLASSID,cnt);
4329ae5db72SJed Brown       ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
4335edff71fSBarry Smith       ierr = VecGetArrayRead(gvec,&array);CHKERRQ(ierr);
4349ae5db72SJed Brown       ierr = VecPlaceArray(global,array+next->rstart);CHKERRQ(ierr);
4359ae5db72SJed Brown       ierr = DMGlobalToLocalBegin(next->dm,global,INSERT_VALUES,local);CHKERRQ(ierr);
4369ae5db72SJed Brown       ierr = DMGlobalToLocalEnd(next->dm,global,INSERT_VALUES,local);CHKERRQ(ierr);
4375edff71fSBarry Smith       ierr = VecRestoreArrayRead(gvec,&array);CHKERRQ(ierr);
4389ae5db72SJed Brown       ierr = VecResetArray(global);CHKERRQ(ierr);
4399ae5db72SJed Brown       ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
44047c6ae99SBarry Smith     }
44147c6ae99SBarry Smith   }
44247c6ae99SBarry Smith   va_end(Argp);
44347c6ae99SBarry Smith   PetscFunctionReturn(0);
44447c6ae99SBarry Smith }
44547c6ae99SBarry Smith 
44647c6ae99SBarry Smith #undef __FUNCT__
4476f3c3dcfSJed Brown #define __FUNCT__ "DMCompositeScatterArray"
4486f3c3dcfSJed Brown /*@
4496f3c3dcfSJed Brown     DMCompositeScatterArray - Scatters from a global packed vector into its individual local vectors
4506f3c3dcfSJed Brown 
4516f3c3dcfSJed Brown     Collective on DMComposite
4526f3c3dcfSJed Brown 
4536f3c3dcfSJed Brown     Input Parameters:
4546f3c3dcfSJed Brown +    dm - the packer object
4556f3c3dcfSJed Brown .    gvec - the global vector
4566f3c3dcfSJed Brown .    lvecs - array of local vectors, NULL for any that are not needed
4576f3c3dcfSJed Brown 
4586f3c3dcfSJed Brown     Level: advanced
4596f3c3dcfSJed Brown 
4606f3c3dcfSJed Brown     Note:
461907376e6SBarry Smith     This is a non-variadic alternative to DMCompositeScatter()
4626f3c3dcfSJed Brown 
4636f3c3dcfSJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector()
4646f3c3dcfSJed Brown          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
4656f3c3dcfSJed Brown          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
4666f3c3dcfSJed Brown 
4676f3c3dcfSJed Brown @*/
4686f3c3dcfSJed Brown PetscErrorCode  DMCompositeScatterArray(DM dm,Vec gvec,Vec *lvecs)
4696f3c3dcfSJed Brown {
4706f3c3dcfSJed Brown   PetscErrorCode         ierr;
4716f3c3dcfSJed Brown   struct DMCompositeLink *next;
4726f3c3dcfSJed Brown   PetscInt               i;
4736f3c3dcfSJed Brown   DM_Composite           *com = (DM_Composite*)dm->data;
4746f3c3dcfSJed Brown 
4756f3c3dcfSJed Brown   PetscFunctionBegin;
4766f3c3dcfSJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4776f3c3dcfSJed Brown   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
4786f3c3dcfSJed Brown   if (!com->setup) {
4796f3c3dcfSJed Brown     ierr = DMSetUp(dm);CHKERRQ(ierr);
4806f3c3dcfSJed Brown   }
4816f3c3dcfSJed Brown 
4826f3c3dcfSJed Brown   /* loop over packed objects, handling one at at time */
4836f3c3dcfSJed Brown   for (i=0,next=com->next; next; next=next->next,i++) {
4846f3c3dcfSJed Brown     if (lvecs[i]) {
4856f3c3dcfSJed Brown       Vec         global;
486c5d31e75SLisandro Dalcin       const PetscScalar *array;
4876f3c3dcfSJed Brown       PetscValidHeaderSpecific(lvecs[i],VEC_CLASSID,3);
4886f3c3dcfSJed Brown       ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
489c5d31e75SLisandro Dalcin       ierr = VecGetArrayRead(gvec,&array);CHKERRQ(ierr);
490c5d31e75SLisandro Dalcin       ierr = VecPlaceArray(global,(PetscScalar*)array+next->rstart);CHKERRQ(ierr);
4916f3c3dcfSJed Brown       ierr = DMGlobalToLocalBegin(next->dm,global,INSERT_VALUES,lvecs[i]);CHKERRQ(ierr);
4926f3c3dcfSJed Brown       ierr = DMGlobalToLocalEnd(next->dm,global,INSERT_VALUES,lvecs[i]);CHKERRQ(ierr);
493c5d31e75SLisandro Dalcin       ierr = VecRestoreArrayRead(gvec,&array);CHKERRQ(ierr);
4946f3c3dcfSJed Brown       ierr = VecResetArray(global);CHKERRQ(ierr);
4956f3c3dcfSJed Brown       ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
4966f3c3dcfSJed Brown     }
4976f3c3dcfSJed Brown   }
4986f3c3dcfSJed Brown   PetscFunctionReturn(0);
4996f3c3dcfSJed Brown }
5006f3c3dcfSJed Brown 
5016f3c3dcfSJed Brown #undef __FUNCT__
50247c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGather"
50347c6ae99SBarry Smith /*@C
50447c6ae99SBarry Smith     DMCompositeGather - Gathers into a global packed vector from its individual local vectors
50547c6ae99SBarry Smith 
50647c6ae99SBarry Smith     Collective on DMComposite
50747c6ae99SBarry Smith 
50847c6ae99SBarry Smith     Input Parameter:
50947c6ae99SBarry Smith +    dm - the packer object
51047c6ae99SBarry Smith .    gvec - the global vector
511907376e6SBarry Smith .    imode - INSERT_VALUES or ADD_VALUES
5120298fd71SBarry Smith -    Vec ... - the individual sequential vectors, NULL for any that are not needed
51347c6ae99SBarry Smith 
51447c6ae99SBarry Smith     Level: advanced
51547c6ae99SBarry Smith 
5169ae5db72SJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
5176eb61c8cSJed Brown          DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
51847c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
51947c6ae99SBarry Smith 
52047c6ae99SBarry Smith @*/
5217087cfbeSBarry Smith PetscErrorCode  DMCompositeGather(DM dm,Vec gvec,InsertMode imode,...)
52247c6ae99SBarry Smith {
52347c6ae99SBarry Smith   va_list                Argp;
52447c6ae99SBarry Smith   PetscErrorCode         ierr;
52547c6ae99SBarry Smith   struct DMCompositeLink *next;
52647c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
5278fd8f222SJed Brown   PetscInt               cnt;
52847c6ae99SBarry Smith 
52947c6ae99SBarry Smith   PetscFunctionBegin;
53047c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
53147c6ae99SBarry Smith   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
53247c6ae99SBarry Smith   if (!com->setup) {
533d7bf68aeSBarry Smith     ierr = DMSetUp(dm);CHKERRQ(ierr);
53447c6ae99SBarry Smith   }
53547c6ae99SBarry Smith 
53647c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
537df0c820aSJed Brown   va_start(Argp,imode);
5388fd8f222SJed Brown   for (cnt=3,next=com->next; next; cnt++,next=next->next) {
5399ae5db72SJed Brown     Vec local;
5409ae5db72SJed Brown     local = va_arg(Argp, Vec);
5419ae5db72SJed Brown     if (local) {
54247c6ae99SBarry Smith       PetscScalar *array;
5439ae5db72SJed Brown       Vec         global;
5449ae5db72SJed Brown       PetscValidHeaderSpecific(local,VEC_CLASSID,cnt);
5459ae5db72SJed Brown       ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
5469ae5db72SJed Brown       ierr = VecGetArray(gvec,&array);CHKERRQ(ierr);
5479ae5db72SJed Brown       ierr = VecPlaceArray(global,array+next->rstart);CHKERRQ(ierr);
5489ae5db72SJed Brown       ierr = DMLocalToGlobalBegin(next->dm,local,imode,global);CHKERRQ(ierr);
5499ae5db72SJed Brown       ierr = DMLocalToGlobalEnd(next->dm,local,imode,global);CHKERRQ(ierr);
5509ae5db72SJed Brown       ierr = VecRestoreArray(gvec,&array);CHKERRQ(ierr);
5519ae5db72SJed Brown       ierr = VecResetArray(global);CHKERRQ(ierr);
5529ae5db72SJed Brown       ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
55347c6ae99SBarry Smith     }
55447c6ae99SBarry Smith   }
55547c6ae99SBarry Smith   va_end(Argp);
55647c6ae99SBarry Smith   PetscFunctionReturn(0);
55747c6ae99SBarry Smith }
55847c6ae99SBarry Smith 
55947c6ae99SBarry Smith #undef __FUNCT__
5606f3c3dcfSJed Brown #define __FUNCT__ "DMCompositeGatherArray"
5616f3c3dcfSJed Brown /*@
5626f3c3dcfSJed Brown     DMCompositeGatherArray - Gathers into a global packed vector from its individual local vectors
5636f3c3dcfSJed Brown 
5646f3c3dcfSJed Brown     Collective on DMComposite
5656f3c3dcfSJed Brown 
5666f3c3dcfSJed Brown     Input Parameter:
5676f3c3dcfSJed Brown +    dm - the packer object
5686f3c3dcfSJed Brown .    gvec - the global vector
569907376e6SBarry Smith .    imode - INSERT_VALUES or ADD_VALUES
5706f3c3dcfSJed Brown -    lvecs - the individual sequential vectors, NULL for any that are not needed
5716f3c3dcfSJed Brown 
5726f3c3dcfSJed Brown     Level: advanced
5736f3c3dcfSJed Brown 
5746f3c3dcfSJed Brown     Notes:
5756f3c3dcfSJed Brown     This is a non-variadic alternative to DMCompositeGather().
5766f3c3dcfSJed Brown 
5776f3c3dcfSJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
5786f3c3dcfSJed Brown          DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
5796f3c3dcfSJed Brown          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries(),
5806f3c3dcfSJed Brown @*/
5816f3c3dcfSJed Brown PetscErrorCode  DMCompositeGatherArray(DM dm,Vec gvec,InsertMode imode,Vec *lvecs)
5826f3c3dcfSJed Brown {
5836f3c3dcfSJed Brown   PetscErrorCode         ierr;
5846f3c3dcfSJed Brown   struct DMCompositeLink *next;
5856f3c3dcfSJed Brown   DM_Composite           *com = (DM_Composite*)dm->data;
5866f3c3dcfSJed Brown   PetscInt               i;
5876f3c3dcfSJed Brown 
5886f3c3dcfSJed Brown   PetscFunctionBegin;
5896f3c3dcfSJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
5906f3c3dcfSJed Brown   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
5916f3c3dcfSJed Brown   if (!com->setup) {
5926f3c3dcfSJed Brown     ierr = DMSetUp(dm);CHKERRQ(ierr);
5936f3c3dcfSJed Brown   }
5946f3c3dcfSJed Brown 
5956f3c3dcfSJed Brown   /* loop over packed objects, handling one at at time */
5966f3c3dcfSJed Brown   for (next=com->next,i=0; next; next=next->next,i++) {
5976f3c3dcfSJed Brown     if (lvecs[i]) {
5986f3c3dcfSJed Brown       PetscScalar *array;
5996f3c3dcfSJed Brown       Vec         global;
6006f3c3dcfSJed Brown       PetscValidHeaderSpecific(lvecs[i],VEC_CLASSID,3);
6016f3c3dcfSJed Brown       ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
6026f3c3dcfSJed Brown       ierr = VecGetArray(gvec,&array);CHKERRQ(ierr);
6036f3c3dcfSJed Brown       ierr = VecPlaceArray(global,array+next->rstart);CHKERRQ(ierr);
6046f3c3dcfSJed Brown       ierr = DMLocalToGlobalBegin(next->dm,lvecs[i],imode,global);CHKERRQ(ierr);
6056f3c3dcfSJed Brown       ierr = DMLocalToGlobalEnd(next->dm,lvecs[i],imode,global);CHKERRQ(ierr);
6066f3c3dcfSJed Brown       ierr = VecRestoreArray(gvec,&array);CHKERRQ(ierr);
6076f3c3dcfSJed Brown       ierr = VecResetArray(global);CHKERRQ(ierr);
6086f3c3dcfSJed Brown       ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
6096f3c3dcfSJed Brown     }
6106f3c3dcfSJed Brown   }
6116f3c3dcfSJed Brown   PetscFunctionReturn(0);
6126f3c3dcfSJed Brown }
6136f3c3dcfSJed Brown 
6146f3c3dcfSJed Brown #undef __FUNCT__
61547c6ae99SBarry Smith #define __FUNCT__ "DMCompositeAddDM"
61647c6ae99SBarry Smith /*@C
617aa219208SBarry Smith     DMCompositeAddDM - adds a DM  vector to a DMComposite
61847c6ae99SBarry Smith 
61947c6ae99SBarry Smith     Collective on DMComposite
62047c6ae99SBarry Smith 
62147c6ae99SBarry Smith     Input Parameter:
62247c6ae99SBarry Smith +    dm - the packer object
62347c6ae99SBarry Smith -    dm - the DM object, if the DM is a da you will need to caste it with a (DM)
62447c6ae99SBarry Smith 
62547c6ae99SBarry Smith     Level: advanced
62647c6ae99SBarry Smith 
6270c010503SBarry Smith .seealso DMDestroy(), DMCompositeGather(), DMCompositeAddDM(), DMCreateGlobalVector(),
6286eb61c8cSJed Brown          DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
62947c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
63047c6ae99SBarry Smith 
63147c6ae99SBarry Smith @*/
6327087cfbeSBarry Smith PetscErrorCode  DMCompositeAddDM(DM dmc,DM dm)
63347c6ae99SBarry Smith {
63447c6ae99SBarry Smith   PetscErrorCode         ierr;
63506ebdd98SJed Brown   PetscInt               n,nlocal;
63647c6ae99SBarry Smith   struct DMCompositeLink *mine,*next;
63706ebdd98SJed Brown   Vec                    global,local;
63847c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dmc->data;
63947c6ae99SBarry Smith 
64047c6ae99SBarry Smith   PetscFunctionBegin;
64147c6ae99SBarry Smith   PetscValidHeaderSpecific(dmc,DM_CLASSID,1);
64247c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,2);
64347c6ae99SBarry Smith   next = com->next;
644ce94432eSBarry Smith   if (com->setup) SETERRQ(PetscObjectComm((PetscObject)dmc),PETSC_ERR_ARG_WRONGSTATE,"Cannot add a DM once you have used the DMComposite");
64547c6ae99SBarry Smith 
64647c6ae99SBarry Smith   /* create new link */
647b00a9115SJed Brown   ierr = PetscNew(&mine);CHKERRQ(ierr);
64847c6ae99SBarry Smith   ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
64947c6ae99SBarry Smith   ierr = DMGetGlobalVector(dm,&global);CHKERRQ(ierr);
65047c6ae99SBarry Smith   ierr = VecGetLocalSize(global,&n);CHKERRQ(ierr);
65147c6ae99SBarry Smith   ierr = DMRestoreGlobalVector(dm,&global);CHKERRQ(ierr);
65206ebdd98SJed Brown   ierr = DMGetLocalVector(dm,&local);CHKERRQ(ierr);
65306ebdd98SJed Brown   ierr = VecGetSize(local,&nlocal);CHKERRQ(ierr);
65406ebdd98SJed Brown   ierr = DMRestoreLocalVector(dm,&local);CHKERRQ(ierr);
6558865f1eaSKarl Rupp 
65647c6ae99SBarry Smith   mine->n      = n;
65706ebdd98SJed Brown   mine->nlocal = nlocal;
65847c6ae99SBarry Smith   mine->dm     = dm;
6590298fd71SBarry Smith   mine->next   = NULL;
66047c6ae99SBarry Smith   com->n      += n;
66147c6ae99SBarry Smith 
66247c6ae99SBarry Smith   /* add to end of list */
6638865f1eaSKarl Rupp   if (!next) com->next = mine;
6648865f1eaSKarl Rupp   else {
66547c6ae99SBarry Smith     while (next->next) next = next->next;
66647c6ae99SBarry Smith     next->next = mine;
66747c6ae99SBarry Smith   }
66847c6ae99SBarry Smith   com->nDM++;
66947c6ae99SBarry Smith   com->nmine++;
67047c6ae99SBarry Smith   PetscFunctionReturn(0);
67147c6ae99SBarry Smith }
67247c6ae99SBarry Smith 
6739804daf3SBarry Smith #include <petscdraw.h>
67426887b52SJed Brown PETSC_EXTERN PetscErrorCode  VecView_MPI(Vec,PetscViewer);
67547c6ae99SBarry Smith #undef __FUNCT__
67647c6ae99SBarry Smith #define __FUNCT__ "VecView_DMComposite"
6777087cfbeSBarry Smith PetscErrorCode  VecView_DMComposite(Vec gvec,PetscViewer viewer)
67847c6ae99SBarry Smith {
67947c6ae99SBarry Smith   DM                     dm;
68047c6ae99SBarry Smith   PetscErrorCode         ierr;
68147c6ae99SBarry Smith   struct DMCompositeLink *next;
68247c6ae99SBarry Smith   PetscBool              isdraw;
683cef07954SSatish Balay   DM_Composite           *com;
68447c6ae99SBarry Smith 
68547c6ae99SBarry Smith   PetscFunctionBegin;
686c688c046SMatthew G Knepley   ierr = VecGetDM(gvec, &dm);CHKERRQ(ierr);
687ce94432eSBarry Smith   if (!dm) SETERRQ(PetscObjectComm((PetscObject)gvec),PETSC_ERR_ARG_WRONG,"Vector not generated from a DMComposite");
68847c6ae99SBarry Smith   com  = (DM_Composite*)dm->data;
68947c6ae99SBarry Smith   next = com->next;
69047c6ae99SBarry Smith 
691251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
69247c6ae99SBarry Smith   if (!isdraw) {
69347c6ae99SBarry Smith     /* do I really want to call this? */
69447c6ae99SBarry Smith     ierr = VecView_MPI(gvec,viewer);CHKERRQ(ierr);
69547c6ae99SBarry Smith   } else {
69647c6ae99SBarry Smith     PetscInt cnt = 0;
69747c6ae99SBarry Smith 
69847c6ae99SBarry Smith     /* loop over packed objects, handling one at at time */
69947c6ae99SBarry Smith     while (next) {
70047c6ae99SBarry Smith       Vec         vec;
7019ae5db72SJed Brown       PetscScalar *array;
70247c6ae99SBarry Smith       PetscInt    bs;
70347c6ae99SBarry Smith 
7049ae5db72SJed Brown       /* Should use VecGetSubVector() eventually, but would need to forward the DM for that to work */
7059ae5db72SJed Brown       ierr = DMGetGlobalVector(next->dm,&vec);CHKERRQ(ierr);
7069ae5db72SJed Brown       ierr = VecGetArray(gvec,&array);CHKERRQ(ierr);
7079ae5db72SJed Brown       ierr = VecPlaceArray(vec,array+next->rstart);CHKERRQ(ierr);
7089ae5db72SJed Brown       ierr = VecRestoreArray(gvec,&array);CHKERRQ(ierr);
70947c6ae99SBarry Smith       ierr = VecView(vec,viewer);CHKERRQ(ierr);
71047c6ae99SBarry Smith       ierr = VecGetBlockSize(vec,&bs);CHKERRQ(ierr);
7119ae5db72SJed Brown       ierr = VecResetArray(vec);CHKERRQ(ierr);
7129ae5db72SJed Brown       ierr = DMRestoreGlobalVector(next->dm,&vec);CHKERRQ(ierr);
71347c6ae99SBarry Smith       ierr = PetscViewerDrawBaseAdd(viewer,bs);CHKERRQ(ierr);
71447c6ae99SBarry Smith       cnt += bs;
71547c6ae99SBarry Smith       next = next->next;
71647c6ae99SBarry Smith     }
71747c6ae99SBarry Smith     ierr = PetscViewerDrawBaseAdd(viewer,-cnt);CHKERRQ(ierr);
71847c6ae99SBarry Smith   }
71947c6ae99SBarry Smith   PetscFunctionReturn(0);
72047c6ae99SBarry Smith }
72147c6ae99SBarry Smith 
72247c6ae99SBarry Smith #undef __FUNCT__
7230c010503SBarry Smith #define __FUNCT__ "DMCreateGlobalVector_Composite"
7247087cfbeSBarry Smith PetscErrorCode  DMCreateGlobalVector_Composite(DM dm,Vec *gvec)
72547c6ae99SBarry Smith {
72647c6ae99SBarry Smith   PetscErrorCode ierr;
72747c6ae99SBarry Smith   DM_Composite   *com = (DM_Composite*)dm->data;
72847c6ae99SBarry Smith 
72947c6ae99SBarry Smith   PetscFunctionBegin;
73047c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
731d7bf68aeSBarry Smith   ierr = DMSetUp(dm);CHKERRQ(ierr);
732ce94432eSBarry Smith   ierr = VecCreateMPI(PetscObjectComm((PetscObject)dm),com->n,com->N,gvec);CHKERRQ(ierr);
733c688c046SMatthew G Knepley   ierr = VecSetDM(*gvec, dm);CHKERRQ(ierr);
73447c6ae99SBarry Smith   ierr = VecSetOperation(*gvec,VECOP_VIEW,(void (*)(void))VecView_DMComposite);CHKERRQ(ierr);
73547c6ae99SBarry Smith   PetscFunctionReturn(0);
73647c6ae99SBarry Smith }
73747c6ae99SBarry Smith 
73847c6ae99SBarry Smith #undef __FUNCT__
7390c010503SBarry Smith #define __FUNCT__ "DMCreateLocalVector_Composite"
7407087cfbeSBarry Smith PetscErrorCode  DMCreateLocalVector_Composite(DM dm,Vec *lvec)
74147c6ae99SBarry Smith {
74247c6ae99SBarry Smith   PetscErrorCode ierr;
74347c6ae99SBarry Smith   DM_Composite   *com = (DM_Composite*)dm->data;
74447c6ae99SBarry Smith 
74547c6ae99SBarry Smith   PetscFunctionBegin;
74647c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
74747c6ae99SBarry Smith   if (!com->setup) {
748d7bf68aeSBarry Smith     ierr = DMSetUp(dm);CHKERRQ(ierr);
74947c6ae99SBarry Smith   }
750ce94432eSBarry Smith   ierr = VecCreateSeq(PetscObjectComm((PetscObject)dm),com->nghost,lvec);CHKERRQ(ierr);
751c688c046SMatthew G Knepley   ierr = VecSetDM(*lvec, dm);CHKERRQ(ierr);
75247c6ae99SBarry Smith   PetscFunctionReturn(0);
75347c6ae99SBarry Smith }
75447c6ae99SBarry Smith 
75547c6ae99SBarry Smith #undef __FUNCT__
7566eb61c8cSJed Brown #define __FUNCT__ "DMCompositeGetISLocalToGlobalMappings"
75747c6ae99SBarry Smith /*@C
7589ae5db72SJed Brown     DMCompositeGetISLocalToGlobalMappings - gets an ISLocalToGlobalMapping for each DM in the DMComposite, maps to the composite global space
75947c6ae99SBarry Smith 
76006ebdd98SJed Brown     Collective on DM
76147c6ae99SBarry Smith 
76247c6ae99SBarry Smith     Input Parameter:
76347c6ae99SBarry Smith .    dm - the packer object
76447c6ae99SBarry Smith 
76547c6ae99SBarry Smith     Output Parameters:
7669ae5db72SJed Brown .    ltogs - the individual mappings for each packed vector. Note that this includes
7679ae5db72SJed Brown            all the ghost points that individual ghosted DMDA's may have.
76847c6ae99SBarry Smith 
76947c6ae99SBarry Smith     Level: advanced
77047c6ae99SBarry Smith 
77147c6ae99SBarry Smith     Notes:
7726eb61c8cSJed Brown        Each entry of ltogs should be destroyed with ISLocalToGlobalMappingDestroy(), the ltogs array should be freed with PetscFree().
77347c6ae99SBarry Smith 
7749ae5db72SJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
77547c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetAccess(), DMCompositeScatter(),
77647c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(),DMCompositeGetEntries()
77747c6ae99SBarry Smith 
77847c6ae99SBarry Smith @*/
7797087cfbeSBarry Smith PetscErrorCode  DMCompositeGetISLocalToGlobalMappings(DM dm,ISLocalToGlobalMapping **ltogs)
78047c6ae99SBarry Smith {
78147c6ae99SBarry Smith   PetscErrorCode         ierr;
78247c6ae99SBarry Smith   PetscInt               i,*idx,n,cnt;
78347c6ae99SBarry Smith   struct DMCompositeLink *next;
78447c6ae99SBarry Smith   PetscMPIInt            rank;
78547c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
78647c6ae99SBarry Smith 
78747c6ae99SBarry Smith   PetscFunctionBegin;
78847c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
789728e99d6SJed Brown   ierr = DMSetUp(dm);CHKERRQ(ierr);
790854ce69bSBarry Smith   ierr = PetscMalloc1(com->nDM,ltogs);CHKERRQ(ierr);
79147c6ae99SBarry Smith   next = com->next;
792ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
79347c6ae99SBarry Smith 
79447c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
79547c6ae99SBarry Smith   cnt = 0;
79647c6ae99SBarry Smith   while (next) {
7976eb61c8cSJed Brown     ISLocalToGlobalMapping ltog;
7986eb61c8cSJed Brown     PetscMPIInt            size;
79986994e45SJed Brown     const PetscInt         *suboff,*indices;
8006eb61c8cSJed Brown     Vec                    global;
80147c6ae99SBarry Smith 
8026eb61c8cSJed Brown     /* Get sub-DM global indices for each local dof */
8031411c6eeSJed Brown     ierr = DMGetLocalToGlobalMapping(next->dm,&ltog);CHKERRQ(ierr);
8046eb61c8cSJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltog,&n);CHKERRQ(ierr);
80586994e45SJed Brown     ierr = ISLocalToGlobalMappingGetIndices(ltog,&indices);CHKERRQ(ierr);
806785e854fSJed Brown     ierr = PetscMalloc1(n,&idx);CHKERRQ(ierr);
80747c6ae99SBarry Smith 
8086eb61c8cSJed Brown     /* Get the offsets for the sub-DM global vector */
8096eb61c8cSJed Brown     ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
8106eb61c8cSJed Brown     ierr = VecGetOwnershipRanges(global,&suboff);CHKERRQ(ierr);
811ce94432eSBarry Smith     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)global),&size);CHKERRQ(ierr);
8126eb61c8cSJed Brown 
8136eb61c8cSJed Brown     /* Shift the sub-DM definition of the global space to the composite global space */
8146eb61c8cSJed Brown     for (i=0; i<n; i++) {
81586994e45SJed Brown       PetscInt subi = indices[i],lo = 0,hi = size,t;
8166eb61c8cSJed Brown       /* Binary search to find which rank owns subi */
8176eb61c8cSJed Brown       while (hi-lo > 1) {
8186eb61c8cSJed Brown         t = lo + (hi-lo)/2;
8196eb61c8cSJed Brown         if (suboff[t] > subi) hi = t;
8206eb61c8cSJed Brown         else                  lo = t;
8216eb61c8cSJed Brown       }
8226eb61c8cSJed Brown       idx[i] = subi - suboff[lo] + next->grstarts[lo];
8236eb61c8cSJed Brown     }
82486994e45SJed Brown     ierr = ISLocalToGlobalMappingRestoreIndices(ltog,&indices);CHKERRQ(ierr);
825f0413b6fSBarry Smith     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm),1,n,idx,PETSC_OWN_POINTER,&(*ltogs)[cnt]);CHKERRQ(ierr);
8266eb61c8cSJed Brown     ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
82747c6ae99SBarry Smith     next = next->next;
82847c6ae99SBarry Smith     cnt++;
82947c6ae99SBarry Smith   }
83047c6ae99SBarry Smith   PetscFunctionReturn(0);
83147c6ae99SBarry Smith }
83247c6ae99SBarry Smith 
83347c6ae99SBarry Smith #undef __FUNCT__
83487c85e80SJed Brown #define __FUNCT__ "DMCompositeGetLocalISs"
83587c85e80SJed Brown /*@C
8369ae5db72SJed Brown    DMCompositeGetLocalISs - Gets index sets for each component of a composite local vector
83787c85e80SJed Brown 
83887c85e80SJed Brown    Not Collective
83987c85e80SJed Brown 
84087c85e80SJed Brown    Input Arguments:
84187c85e80SJed Brown . dm - composite DM
84287c85e80SJed Brown 
84387c85e80SJed Brown    Output Arguments:
84487c85e80SJed Brown . is - array of serial index sets for each each component of the DMComposite
84587c85e80SJed Brown 
84687c85e80SJed Brown    Level: intermediate
84787c85e80SJed Brown 
84887c85e80SJed Brown    Notes:
84987c85e80SJed Brown    At present, a composite local vector does not normally exist.  This function is used to provide index sets for
85087c85e80SJed Brown    MatGetLocalSubMatrix().  In the future, the scatters for each entry in the DMComposite may be be merged into a single
8519ae5db72SJed Brown    scatter to a composite local vector.  The user should not typically need to know which is being done.
85287c85e80SJed Brown 
85387c85e80SJed Brown    To get the composite global indices at all local points (including ghosts), use DMCompositeGetISLocalToGlobalMappings().
85487c85e80SJed Brown 
85587c85e80SJed Brown    To get index sets for pieces of the composite global vector, use DMCompositeGetGlobalISs().
85687c85e80SJed Brown 
85787c85e80SJed Brown    Each returned IS should be destroyed with ISDestroy(), the array should be freed with PetscFree().
85887c85e80SJed Brown 
85987c85e80SJed Brown .seealso: DMCompositeGetGlobalISs(), DMCompositeGetISLocalToGlobalMappings(), MatGetLocalSubMatrix(), MatCreateLocalRef()
86087c85e80SJed Brown @*/
8617087cfbeSBarry Smith PetscErrorCode  DMCompositeGetLocalISs(DM dm,IS **is)
86287c85e80SJed Brown {
86387c85e80SJed Brown   PetscErrorCode         ierr;
86487c85e80SJed Brown   DM_Composite           *com = (DM_Composite*)dm->data;
86587c85e80SJed Brown   struct DMCompositeLink *link;
86687c85e80SJed Brown   PetscInt               cnt,start;
86787c85e80SJed Brown 
86887c85e80SJed Brown   PetscFunctionBegin;
86987c85e80SJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
87087c85e80SJed Brown   PetscValidPointer(is,2);
871785e854fSJed Brown   ierr = PetscMalloc1(com->nmine,is);CHKERRQ(ierr);
87206ebdd98SJed Brown   for (cnt=0,start=0,link=com->next; link; start+=link->nlocal,cnt++,link=link->next) {
873520db06cSJed Brown     PetscInt bs;
8749ae5db72SJed Brown     ierr = ISCreateStride(PETSC_COMM_SELF,link->nlocal,start,1,&(*is)[cnt]);CHKERRQ(ierr);
8751411c6eeSJed Brown     ierr = DMGetBlockSize(link->dm,&bs);CHKERRQ(ierr);
876520db06cSJed Brown     ierr = ISSetBlockSize((*is)[cnt],bs);CHKERRQ(ierr);
877520db06cSJed Brown   }
87887c85e80SJed Brown   PetscFunctionReturn(0);
87987c85e80SJed Brown }
88087c85e80SJed Brown 
88187c85e80SJed Brown #undef __FUNCT__
88247c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetGlobalISs"
88347c6ae99SBarry Smith /*@C
88447c6ae99SBarry Smith     DMCompositeGetGlobalISs - Gets the index sets for each composed object
88547c6ae99SBarry Smith 
88647c6ae99SBarry Smith     Collective on DMComposite
88747c6ae99SBarry Smith 
88847c6ae99SBarry Smith     Input Parameter:
88947c6ae99SBarry Smith .    dm - the packer object
89047c6ae99SBarry Smith 
89147c6ae99SBarry Smith     Output Parameters:
89247c6ae99SBarry Smith .    is - the array of index sets
89347c6ae99SBarry Smith 
89447c6ae99SBarry Smith     Level: advanced
89547c6ae99SBarry Smith 
89647c6ae99SBarry Smith     Notes:
89747c6ae99SBarry Smith        The is entries should be destroyed with ISDestroy(), the is array should be freed with PetscFree()
89847c6ae99SBarry Smith 
89947c6ae99SBarry Smith        These could be used to extract a subset of vector entries for a "multi-physics" preconditioner
90047c6ae99SBarry Smith 
9016eb61c8cSJed Brown        Use DMCompositeGetLocalISs() for index sets in the packed local numbering, and
9026eb61c8cSJed Brown        DMCompositeGetISLocalToGlobalMappings() for to map local sub-DM (including ghost) indices to packed global
9036eb61c8cSJed Brown        indices.
90447c6ae99SBarry Smith 
9059ae5db72SJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
90647c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetAccess(), DMCompositeScatter(),
90747c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(),DMCompositeGetEntries()
90847c6ae99SBarry Smith 
90947c6ae99SBarry Smith @*/
9106eb61c8cSJed Brown 
9117087cfbeSBarry Smith PetscErrorCode  DMCompositeGetGlobalISs(DM dm,IS *is[])
91247c6ae99SBarry Smith {
91347c6ae99SBarry Smith   PetscErrorCode         ierr;
91466bb578eSMark Adams   PetscInt               cnt = 0;
91547c6ae99SBarry Smith   struct DMCompositeLink *next;
91647c6ae99SBarry Smith   PetscMPIInt            rank;
91747c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
91847c6ae99SBarry Smith 
91947c6ae99SBarry Smith   PetscFunctionBegin;
92047c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
921854ce69bSBarry Smith   ierr = PetscMalloc1(com->nDM,is);CHKERRQ(ierr);
92247c6ae99SBarry Smith   next = com->next;
923ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
92447c6ae99SBarry Smith 
92547c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
92647c6ae99SBarry Smith   while (next) {
92766bb578eSMark Adams     ierr = ISCreateStride(PetscObjectComm((PetscObject)dm),next->n,next->grstart,1,&(*is)[cnt]);CHKERRQ(ierr);
9280f21e855SMatthew G. Knepley     if (dm->prob) {
92965c226d8SMatthew G. Knepley       MatNullSpace space;
93065c226d8SMatthew G. Knepley       Mat          pmat;
9310f21e855SMatthew G. Knepley       PetscObject  disc;
9320f21e855SMatthew G. Knepley       PetscInt     Nf;
93365c226d8SMatthew G. Knepley 
9342764a2aaSMatthew G. Knepley       ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr);
935f24dd8d2SMatthew G. Knepley       if (cnt < Nf) {
9362764a2aaSMatthew G. Knepley         ierr = PetscDSGetDiscretization(dm->prob, cnt, &disc);CHKERRQ(ierr);
9370f21e855SMatthew G. Knepley         ierr = PetscObjectQuery(disc, "nullspace", (PetscObject*) &space);CHKERRQ(ierr);
938aac2dd2dSMatthew G. Knepley         if (space) {ierr = PetscObjectCompose((PetscObject) (*is)[cnt], "nullspace", (PetscObject) space);CHKERRQ(ierr);}
9390f21e855SMatthew G. Knepley         ierr = PetscObjectQuery(disc, "nearnullspace", (PetscObject*) &space);CHKERRQ(ierr);
940aac2dd2dSMatthew G. Knepley         if (space) {ierr = PetscObjectCompose((PetscObject) (*is)[cnt], "nearnullspace", (PetscObject) space);CHKERRQ(ierr);}
9410f21e855SMatthew G. Knepley         ierr = PetscObjectQuery(disc, "pmat", (PetscObject*) &pmat);CHKERRQ(ierr);
942aac2dd2dSMatthew G. Knepley         if (pmat) {ierr = PetscObjectCompose((PetscObject) (*is)[cnt], "pmat", (PetscObject) pmat);CHKERRQ(ierr);}
94365c226d8SMatthew G. Knepley       }
944f24dd8d2SMatthew G. Knepley     }
94547c6ae99SBarry Smith     cnt++;
94647c6ae99SBarry Smith     next = next->next;
94747c6ae99SBarry Smith   }
94847c6ae99SBarry Smith   PetscFunctionReturn(0);
94947c6ae99SBarry Smith }
95047c6ae99SBarry Smith 
9514d343eeaSMatthew G Knepley #undef __FUNCT__
9524d343eeaSMatthew G Knepley #define __FUNCT__ "DMCreateFieldIS_Composite"
95321c9b008SJed Brown PetscErrorCode DMCreateFieldIS_Composite(DM dm, PetscInt *numFields,char ***fieldNames, IS **fields)
9544d343eeaSMatthew G Knepley {
9554d343eeaSMatthew G Knepley   PetscInt       nDM;
9564d343eeaSMatthew G Knepley   DM             *dms;
9574d343eeaSMatthew G Knepley   PetscInt       i;
9584d343eeaSMatthew G Knepley   PetscErrorCode ierr;
9594d343eeaSMatthew G Knepley 
9604d343eeaSMatthew G Knepley   PetscFunctionBegin;
9614d343eeaSMatthew G Knepley   ierr = DMCompositeGetNumberDM(dm, &nDM);CHKERRQ(ierr);
9628865f1eaSKarl Rupp   if (numFields) *numFields = nDM;
9634d343eeaSMatthew G Knepley   ierr = DMCompositeGetGlobalISs(dm, fields);CHKERRQ(ierr);
9644d343eeaSMatthew G Knepley   if (fieldNames) {
965785e854fSJed Brown     ierr = PetscMalloc1(nDM, &dms);CHKERRQ(ierr);
966785e854fSJed Brown     ierr = PetscMalloc1(nDM, fieldNames);CHKERRQ(ierr);
9674d343eeaSMatthew G Knepley     ierr = DMCompositeGetEntriesArray(dm, dms);CHKERRQ(ierr);
9684d343eeaSMatthew G Knepley     for (i=0; i<nDM; i++) {
9694d343eeaSMatthew G Knepley       char       buf[256];
9704d343eeaSMatthew G Knepley       const char *splitname;
9714d343eeaSMatthew G Knepley 
9724d343eeaSMatthew G Knepley       /* Split naming precedence: object name, prefix, number */
9734d343eeaSMatthew G Knepley       splitname = ((PetscObject) dm)->name;
9744d343eeaSMatthew G Knepley       if (!splitname) {
9754d343eeaSMatthew G Knepley         ierr = PetscObjectGetOptionsPrefix((PetscObject)dms[i],&splitname);CHKERRQ(ierr);
9764d343eeaSMatthew G Knepley         if (splitname) {
9774d343eeaSMatthew G Knepley           size_t len;
9788caf3d72SBarry Smith           ierr                 = PetscStrncpy(buf,splitname,sizeof(buf));CHKERRQ(ierr);
9798caf3d72SBarry Smith           buf[sizeof(buf) - 1] = 0;
9804d343eeaSMatthew G Knepley           ierr                 = PetscStrlen(buf,&len);CHKERRQ(ierr);
9814d343eeaSMatthew G Knepley           if (buf[len-1] == '_') buf[len-1] = 0; /* Remove trailing underscore if it was used */
9824d343eeaSMatthew G Knepley           splitname = buf;
9834d343eeaSMatthew G Knepley         }
9844d343eeaSMatthew G Knepley       }
9854d343eeaSMatthew G Knepley       if (!splitname) {
9868caf3d72SBarry Smith         ierr      = PetscSNPrintf(buf,sizeof(buf),"%D",i);CHKERRQ(ierr);
9874d343eeaSMatthew G Knepley         splitname = buf;
9884d343eeaSMatthew G Knepley       }
98921c9b008SJed Brown       ierr = PetscStrallocpy(splitname,&(*fieldNames)[i]);CHKERRQ(ierr);
9904d343eeaSMatthew G Knepley     }
9914d343eeaSMatthew G Knepley     ierr = PetscFree(dms);CHKERRQ(ierr);
9924d343eeaSMatthew G Knepley   }
9934d343eeaSMatthew G Knepley   PetscFunctionReturn(0);
9944d343eeaSMatthew G Knepley }
9954d343eeaSMatthew G Knepley 
996e7c4fc90SDmitry Karpeev /*
997e7c4fc90SDmitry Karpeev  This could take over from DMCreateFieldIS(), as it is more general,
9980298fd71SBarry Smith  making DMCreateFieldIS() a special case -- calling with dmlist == NULL;
999e7c4fc90SDmitry Karpeev  At this point it's probably best to be less intrusive, however.
1000e7c4fc90SDmitry Karpeev  */
1001e7c4fc90SDmitry Karpeev #undef __FUNCT__
100216621825SDmitry Karpeev #define __FUNCT__ "DMCreateFieldDecomposition_Composite"
100316621825SDmitry Karpeev PetscErrorCode DMCreateFieldDecomposition_Composite(DM dm, PetscInt *len,char ***namelist, IS **islist, DM **dmlist)
1004e7c4fc90SDmitry Karpeev {
1005e7c4fc90SDmitry Karpeev   PetscInt       nDM;
1006e7c4fc90SDmitry Karpeev   PetscInt       i;
1007e7c4fc90SDmitry Karpeev   PetscErrorCode ierr;
1008e7c4fc90SDmitry Karpeev 
1009e7c4fc90SDmitry Karpeev   PetscFunctionBegin;
1010e7c4fc90SDmitry Karpeev   ierr = DMCreateFieldIS_Composite(dm, len, namelist, islist);CHKERRQ(ierr);
1011e7c4fc90SDmitry Karpeev   if (dmlist) {
1012e7c4fc90SDmitry Karpeev     ierr = DMCompositeGetNumberDM(dm, &nDM);CHKERRQ(ierr);
1013785e854fSJed Brown     ierr = PetscMalloc1(nDM, dmlist);CHKERRQ(ierr);
1014e7c4fc90SDmitry Karpeev     ierr = DMCompositeGetEntriesArray(dm, *dmlist);CHKERRQ(ierr);
1015e7c4fc90SDmitry Karpeev     for (i=0; i<nDM; i++) {
1016e7c4fc90SDmitry Karpeev       ierr = PetscObjectReference((PetscObject)((*dmlist)[i]));CHKERRQ(ierr);
1017e7c4fc90SDmitry Karpeev     }
1018e7c4fc90SDmitry Karpeev   }
1019e7c4fc90SDmitry Karpeev   PetscFunctionReturn(0);
1020e7c4fc90SDmitry Karpeev }
1021e7c4fc90SDmitry Karpeev 
1022e7c4fc90SDmitry Karpeev 
1023e7c4fc90SDmitry Karpeev 
102447c6ae99SBarry Smith /* -------------------------------------------------------------------------------------*/
102547c6ae99SBarry Smith #undef __FUNCT__
102647c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetLocalVectors"
102747c6ae99SBarry Smith /*@C
10289ae5db72SJed Brown     DMCompositeGetLocalVectors - Gets local vectors for each part of a DMComposite.
102947c6ae99SBarry Smith        Use DMCompositeRestoreLocalVectors() to return them.
103047c6ae99SBarry Smith 
103147c6ae99SBarry Smith     Not Collective
103247c6ae99SBarry Smith 
103347c6ae99SBarry Smith     Input Parameter:
103447c6ae99SBarry Smith .    dm - the packer object
103547c6ae99SBarry Smith 
103647c6ae99SBarry Smith     Output Parameter:
10379ae5db72SJed Brown .   Vec ... - the individual sequential Vecs
103847c6ae99SBarry Smith 
103947c6ae99SBarry Smith     Level: advanced
104047c6ae99SBarry Smith 
10419ae5db72SJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
10426eb61c8cSJed Brown          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
104347c6ae99SBarry Smith          DMCompositeRestoreLocalVectors(), DMCompositeScatter(), DMCompositeGetEntries()
104447c6ae99SBarry Smith 
104547c6ae99SBarry Smith @*/
10467087cfbeSBarry Smith PetscErrorCode  DMCompositeGetLocalVectors(DM dm,...)
104747c6ae99SBarry Smith {
104847c6ae99SBarry Smith   va_list                Argp;
104947c6ae99SBarry Smith   PetscErrorCode         ierr;
105047c6ae99SBarry Smith   struct DMCompositeLink *next;
105147c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
105247c6ae99SBarry Smith 
105347c6ae99SBarry Smith   PetscFunctionBegin;
105447c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
105547c6ae99SBarry Smith   next = com->next;
105647c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
105747c6ae99SBarry Smith   va_start(Argp,dm);
105847c6ae99SBarry Smith   while (next) {
105947c6ae99SBarry Smith     Vec *vec;
106047c6ae99SBarry Smith     vec = va_arg(Argp, Vec*);
106106930112SJed Brown     if (vec) {ierr = DMGetLocalVector(next->dm,vec);CHKERRQ(ierr);}
106247c6ae99SBarry Smith     next = next->next;
106347c6ae99SBarry Smith   }
106447c6ae99SBarry Smith   va_end(Argp);
106547c6ae99SBarry Smith   PetscFunctionReturn(0);
106647c6ae99SBarry Smith }
106747c6ae99SBarry Smith 
106847c6ae99SBarry Smith #undef __FUNCT__
106947c6ae99SBarry Smith #define __FUNCT__ "DMCompositeRestoreLocalVectors"
107047c6ae99SBarry Smith /*@C
10719ae5db72SJed Brown     DMCompositeRestoreLocalVectors - Restores local vectors for each part of a DMComposite.
107247c6ae99SBarry Smith 
107347c6ae99SBarry Smith     Not Collective
107447c6ae99SBarry Smith 
107547c6ae99SBarry Smith     Input Parameter:
107647c6ae99SBarry Smith .    dm - the packer object
107747c6ae99SBarry Smith 
107847c6ae99SBarry Smith     Output Parameter:
10799ae5db72SJed Brown .   Vec ... - the individual sequential Vecs
108047c6ae99SBarry Smith 
108147c6ae99SBarry Smith     Level: advanced
108247c6ae99SBarry Smith 
10839ae5db72SJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
10846eb61c8cSJed Brown          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
108547c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeScatter(), DMCompositeGetEntries()
108647c6ae99SBarry Smith 
108747c6ae99SBarry Smith @*/
10887087cfbeSBarry Smith PetscErrorCode  DMCompositeRestoreLocalVectors(DM dm,...)
108947c6ae99SBarry Smith {
109047c6ae99SBarry Smith   va_list                Argp;
109147c6ae99SBarry Smith   PetscErrorCode         ierr;
109247c6ae99SBarry Smith   struct DMCompositeLink *next;
109347c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
109447c6ae99SBarry Smith 
109547c6ae99SBarry Smith   PetscFunctionBegin;
109647c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
109747c6ae99SBarry Smith   next = com->next;
109847c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
109947c6ae99SBarry Smith   va_start(Argp,dm);
110047c6ae99SBarry Smith   while (next) {
110147c6ae99SBarry Smith     Vec *vec;
110247c6ae99SBarry Smith     vec = va_arg(Argp, Vec*);
110306930112SJed Brown     if (vec) {ierr = DMRestoreLocalVector(next->dm,vec);CHKERRQ(ierr);}
110447c6ae99SBarry Smith     next = next->next;
110547c6ae99SBarry Smith   }
110647c6ae99SBarry Smith   va_end(Argp);
110747c6ae99SBarry Smith   PetscFunctionReturn(0);
110847c6ae99SBarry Smith }
110947c6ae99SBarry Smith 
111047c6ae99SBarry Smith /* -------------------------------------------------------------------------------------*/
111147c6ae99SBarry Smith #undef __FUNCT__
111247c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetEntries"
111347c6ae99SBarry Smith /*@C
11149ae5db72SJed Brown     DMCompositeGetEntries - Gets the DM for each entry in a DMComposite.
111547c6ae99SBarry Smith 
111647c6ae99SBarry Smith     Not Collective
111747c6ae99SBarry Smith 
111847c6ae99SBarry Smith     Input Parameter:
111947c6ae99SBarry Smith .    dm - the packer object
112047c6ae99SBarry Smith 
112147c6ae99SBarry Smith     Output Parameter:
11229ae5db72SJed Brown .   DM ... - the individual entries (DMs)
112347c6ae99SBarry Smith 
112447c6ae99SBarry Smith     Level: advanced
112547c6ae99SBarry Smith 
11262fa5ba8aSJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(), DMCompositeGetEntriesArray()
11276eb61c8cSJed Brown          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
112847c6ae99SBarry Smith          DMCompositeRestoreLocalVectors(), DMCompositeGetLocalVectors(),  DMCompositeScatter(),
112947c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors()
113047c6ae99SBarry Smith 
113147c6ae99SBarry Smith @*/
11327087cfbeSBarry Smith PetscErrorCode  DMCompositeGetEntries(DM dm,...)
113347c6ae99SBarry Smith {
113447c6ae99SBarry Smith   va_list                Argp;
113547c6ae99SBarry Smith   struct DMCompositeLink *next;
113647c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
113747c6ae99SBarry Smith 
113847c6ae99SBarry Smith   PetscFunctionBegin;
113947c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
114047c6ae99SBarry Smith   next = com->next;
114147c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
114247c6ae99SBarry Smith   va_start(Argp,dm);
114347c6ae99SBarry Smith   while (next) {
114447c6ae99SBarry Smith     DM *dmn;
114547c6ae99SBarry Smith     dmn = va_arg(Argp, DM*);
11469ae5db72SJed Brown     if (dmn) *dmn = next->dm;
114747c6ae99SBarry Smith     next = next->next;
114847c6ae99SBarry Smith   }
114947c6ae99SBarry Smith   va_end(Argp);
115047c6ae99SBarry Smith   PetscFunctionReturn(0);
115147c6ae99SBarry Smith }
115247c6ae99SBarry Smith 
115347c6ae99SBarry Smith #undef __FUNCT__
11542fa5ba8aSJed Brown #define __FUNCT__ "DMCompositeGetEntriesArray"
1155dbab29e1SMark F. Adams /*@C
11562fa5ba8aSJed Brown     DMCompositeGetEntriesArray - Gets the DM for each entry in a DMComposite.
11572fa5ba8aSJed Brown 
11582fa5ba8aSJed Brown     Not Collective
11592fa5ba8aSJed Brown 
11602fa5ba8aSJed Brown     Input Parameter:
1161907376e6SBarry Smith .    dm - the packer object
1162907376e6SBarry Smith 
1163907376e6SBarry Smith     Output Parameter:
1164907376e6SBarry Smith .    dms - array of sufficient length (see DMCompositeGetNumberDM()) to hold the individual DMs
11652fa5ba8aSJed Brown 
11662fa5ba8aSJed Brown     Level: advanced
11672fa5ba8aSJed Brown 
11682fa5ba8aSJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(), DMCompositeGetEntries()
11692fa5ba8aSJed Brown          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
11702fa5ba8aSJed Brown          DMCompositeRestoreLocalVectors(), DMCompositeGetLocalVectors(),  DMCompositeScatter(),
11712fa5ba8aSJed Brown          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors()
11722fa5ba8aSJed Brown 
11732fa5ba8aSJed Brown @*/
11742fa5ba8aSJed Brown PetscErrorCode DMCompositeGetEntriesArray(DM dm,DM dms[])
11752fa5ba8aSJed Brown {
11762fa5ba8aSJed Brown   struct DMCompositeLink *next;
11772fa5ba8aSJed Brown   DM_Composite           *com = (DM_Composite*)dm->data;
11782fa5ba8aSJed Brown   PetscInt               i;
11792fa5ba8aSJed Brown 
11802fa5ba8aSJed Brown   PetscFunctionBegin;
11812fa5ba8aSJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
11822fa5ba8aSJed Brown   /* loop over packed objects, handling one at at time */
11832fa5ba8aSJed Brown   for (next=com->next,i=0; next; next=next->next,i++) dms[i] = next->dm;
11842fa5ba8aSJed Brown   PetscFunctionReturn(0);
11852fa5ba8aSJed Brown }
11862fa5ba8aSJed Brown 
11872fa5ba8aSJed Brown #undef __FUNCT__
11880c010503SBarry Smith #define __FUNCT__ "DMRefine_Composite"
11897087cfbeSBarry Smith PetscErrorCode  DMRefine_Composite(DM dmi,MPI_Comm comm,DM *fine)
119047c6ae99SBarry Smith {
119147c6ae99SBarry Smith   PetscErrorCode         ierr;
119247c6ae99SBarry Smith   struct DMCompositeLink *next;
119347c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dmi->data;
119447c6ae99SBarry Smith   DM                     dm;
119547c6ae99SBarry Smith 
119647c6ae99SBarry Smith   PetscFunctionBegin;
119747c6ae99SBarry Smith   PetscValidHeaderSpecific(dmi,DM_CLASSID,1);
1198ce94432eSBarry Smith   if (comm == MPI_COMM_NULL) {
1199ce94432eSBarry Smith     ierr = PetscObjectGetComm((PetscObject)dmi,&comm);CHKERRQ(ierr);
1200ce94432eSBarry Smith   }
12012ce3a92bSJed Brown   ierr = DMSetUp(dmi);CHKERRQ(ierr);
120247c6ae99SBarry Smith   next = com->next;
120347c6ae99SBarry Smith   ierr = DMCompositeCreate(comm,fine);CHKERRQ(ierr);
120447c6ae99SBarry Smith 
120547c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
120647c6ae99SBarry Smith   while (next) {
120747c6ae99SBarry Smith     ierr = DMRefine(next->dm,comm,&dm);CHKERRQ(ierr);
120847c6ae99SBarry Smith     ierr = DMCompositeAddDM(*fine,dm);CHKERRQ(ierr);
120947c6ae99SBarry Smith     ierr = PetscObjectDereference((PetscObject)dm);CHKERRQ(ierr);
121047c6ae99SBarry Smith     next = next->next;
121147c6ae99SBarry Smith   }
121247c6ae99SBarry Smith   PetscFunctionReturn(0);
121347c6ae99SBarry Smith }
121447c6ae99SBarry Smith 
121514354c39SJed Brown #undef __FUNCT__
121614354c39SJed Brown #define __FUNCT__ "DMCoarsen_Composite"
121714354c39SJed Brown PetscErrorCode  DMCoarsen_Composite(DM dmi,MPI_Comm comm,DM *fine)
121814354c39SJed Brown {
121914354c39SJed Brown   PetscErrorCode         ierr;
122014354c39SJed Brown   struct DMCompositeLink *next;
122114354c39SJed Brown   DM_Composite           *com = (DM_Composite*)dmi->data;
122214354c39SJed Brown   DM                     dm;
122314354c39SJed Brown 
122414354c39SJed Brown   PetscFunctionBegin;
122514354c39SJed Brown   PetscValidHeaderSpecific(dmi,DM_CLASSID,1);
12262ce3a92bSJed Brown   ierr = DMSetUp(dmi);CHKERRQ(ierr);
12272ee06e3bSJed Brown   if (comm == MPI_COMM_NULL) {
122825296bd5SBarry Smith     ierr = PetscObjectGetComm((PetscObject)dmi,&comm);CHKERRQ(ierr);
122925296bd5SBarry Smith   }
123014354c39SJed Brown   next = com->next;
123114354c39SJed Brown   ierr = DMCompositeCreate(comm,fine);CHKERRQ(ierr);
123214354c39SJed Brown 
123314354c39SJed Brown   /* loop over packed objects, handling one at at time */
123414354c39SJed Brown   while (next) {
123514354c39SJed Brown     ierr = DMCoarsen(next->dm,comm,&dm);CHKERRQ(ierr);
123614354c39SJed Brown     ierr = DMCompositeAddDM(*fine,dm);CHKERRQ(ierr);
123714354c39SJed Brown     ierr = PetscObjectDereference((PetscObject)dm);CHKERRQ(ierr);
123814354c39SJed Brown     next = next->next;
123914354c39SJed Brown   }
124014354c39SJed Brown   PetscFunctionReturn(0);
124114354c39SJed Brown }
124247c6ae99SBarry Smith 
124347c6ae99SBarry Smith #undef __FUNCT__
1244e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_Composite"
1245e727c939SJed Brown PetscErrorCode  DMCreateInterpolation_Composite(DM coarse,DM fine,Mat *A,Vec *v)
124647c6ae99SBarry Smith {
124747c6ae99SBarry Smith   PetscErrorCode         ierr;
12489ae5db72SJed Brown   PetscInt               m,n,M,N,nDM,i;
124947c6ae99SBarry Smith   struct DMCompositeLink *nextc;
125047c6ae99SBarry Smith   struct DMCompositeLink *nextf;
125125296bd5SBarry Smith   Vec                    gcoarse,gfine,*vecs;
125247c6ae99SBarry Smith   DM_Composite           *comcoarse = (DM_Composite*)coarse->data;
125347c6ae99SBarry Smith   DM_Composite           *comfine   = (DM_Composite*)fine->data;
12549ae5db72SJed Brown   Mat                    *mats;
125547c6ae99SBarry Smith 
125647c6ae99SBarry Smith   PetscFunctionBegin;
125747c6ae99SBarry Smith   PetscValidHeaderSpecific(coarse,DM_CLASSID,1);
125847c6ae99SBarry Smith   PetscValidHeaderSpecific(fine,DM_CLASSID,2);
1259f692024eSJed Brown   ierr = DMSetUp(coarse);CHKERRQ(ierr);
1260f692024eSJed Brown   ierr = DMSetUp(fine);CHKERRQ(ierr);
126147c6ae99SBarry Smith   /* use global vectors only for determining matrix layout */
12629ae5db72SJed Brown   ierr = DMGetGlobalVector(coarse,&gcoarse);CHKERRQ(ierr);
12639ae5db72SJed Brown   ierr = DMGetGlobalVector(fine,&gfine);CHKERRQ(ierr);
126447c6ae99SBarry Smith   ierr = VecGetLocalSize(gcoarse,&n);CHKERRQ(ierr);
126547c6ae99SBarry Smith   ierr = VecGetLocalSize(gfine,&m);CHKERRQ(ierr);
126647c6ae99SBarry Smith   ierr = VecGetSize(gcoarse,&N);CHKERRQ(ierr);
126747c6ae99SBarry Smith   ierr = VecGetSize(gfine,&M);CHKERRQ(ierr);
12689ae5db72SJed Brown   ierr = DMRestoreGlobalVector(coarse,&gcoarse);CHKERRQ(ierr);
12699ae5db72SJed Brown   ierr = DMRestoreGlobalVector(fine,&gfine);CHKERRQ(ierr);
127047c6ae99SBarry Smith 
12719ae5db72SJed Brown   nDM = comfine->nDM;
1272ce94432eSBarry Smith   if (nDM != comcoarse->nDM) SETERRQ2(PetscObjectComm((PetscObject)fine),PETSC_ERR_ARG_INCOMP,"Fine DMComposite has %D entries, but coarse has %D",nDM,comcoarse->nDM);
12731795a4d1SJed Brown   ierr = PetscCalloc1(nDM*nDM,&mats);CHKERRQ(ierr);
127425296bd5SBarry Smith   if (v) {
12751795a4d1SJed Brown     ierr = PetscCalloc1(nDM,&vecs);CHKERRQ(ierr);
127625296bd5SBarry Smith   }
127747c6ae99SBarry Smith 
127847c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
12799ae5db72SJed Brown   for (nextc=comcoarse->next,nextf=comfine->next,i=0; nextc; nextc=nextc->next,nextf=nextf->next,i++) {
128025296bd5SBarry Smith     if (!v) {
12810298fd71SBarry Smith       ierr = DMCreateInterpolation(nextc->dm,nextf->dm,&mats[i*nDM+i],NULL);CHKERRQ(ierr);
128225296bd5SBarry Smith     } else {
128325296bd5SBarry Smith       ierr = DMCreateInterpolation(nextc->dm,nextf->dm,&mats[i*nDM+i],&vecs[i]);CHKERRQ(ierr);
128425296bd5SBarry Smith     }
128547c6ae99SBarry Smith   }
1286ce94432eSBarry Smith   ierr = MatCreateNest(PetscObjectComm((PetscObject)fine),nDM,NULL,nDM,NULL,mats,A);CHKERRQ(ierr);
128725296bd5SBarry Smith   if (v) {
1288ce94432eSBarry Smith     ierr = VecCreateNest(PetscObjectComm((PetscObject)fine),nDM,NULL,vecs,v);CHKERRQ(ierr);
128925296bd5SBarry Smith   }
12909ae5db72SJed Brown   for (i=0; i<nDM*nDM; i++) {ierr = MatDestroy(&mats[i]);CHKERRQ(ierr);}
12919ae5db72SJed Brown   ierr = PetscFree(mats);CHKERRQ(ierr);
129225296bd5SBarry Smith   if (v) {
129325296bd5SBarry Smith     for (i=0; i<nDM; i++) {ierr = VecDestroy(&vecs[i]);CHKERRQ(ierr);}
129425296bd5SBarry Smith     ierr = PetscFree(vecs);CHKERRQ(ierr);
129525296bd5SBarry Smith   }
129647c6ae99SBarry Smith   PetscFunctionReturn(0);
129747c6ae99SBarry Smith }
129847c6ae99SBarry Smith 
129947c6ae99SBarry Smith #undef __FUNCT__
1300184d77edSJed Brown #define __FUNCT__ "DMGetLocalToGlobalMapping_Composite"
1301184d77edSJed Brown static PetscErrorCode DMGetLocalToGlobalMapping_Composite(DM dm)
13021411c6eeSJed Brown {
13031411c6eeSJed Brown   DM_Composite           *com = (DM_Composite*)dm->data;
13041411c6eeSJed Brown   ISLocalToGlobalMapping *ltogs;
1305f7efa3c7SJed Brown   PetscInt               i;
13061411c6eeSJed Brown   PetscErrorCode         ierr;
13071411c6eeSJed Brown 
13081411c6eeSJed Brown   PetscFunctionBegin;
13091411c6eeSJed Brown   /* Set the ISLocalToGlobalMapping on the new matrix */
13101411c6eeSJed Brown   ierr = DMCompositeGetISLocalToGlobalMappings(dm,&ltogs);CHKERRQ(ierr);
1311ce94432eSBarry Smith   ierr = ISLocalToGlobalMappingConcatenate(PetscObjectComm((PetscObject)dm),com->nDM,ltogs,&dm->ltogmap);CHKERRQ(ierr);
13129ae5db72SJed Brown   for (i=0; i<com->nDM; i++) {ierr = ISLocalToGlobalMappingDestroy(&ltogs[i]);CHKERRQ(ierr);}
13131411c6eeSJed Brown   ierr = PetscFree(ltogs);CHKERRQ(ierr);
13141411c6eeSJed Brown   PetscFunctionReturn(0);
13151411c6eeSJed Brown }
13161411c6eeSJed Brown 
13171411c6eeSJed Brown 
13181411c6eeSJed Brown #undef __FUNCT__
1319e727c939SJed Brown #define __FUNCT__ "DMCreateColoring_Composite"
1320b412c318SBarry Smith PetscErrorCode  DMCreateColoring_Composite(DM dm,ISColoringType ctype,ISColoring *coloring)
132147c6ae99SBarry Smith {
132247c6ae99SBarry Smith   PetscErrorCode  ierr;
132347c6ae99SBarry Smith   PetscInt        n,i,cnt;
132447c6ae99SBarry Smith   ISColoringValue *colors;
132547c6ae99SBarry Smith   PetscBool       dense  = PETSC_FALSE;
132647c6ae99SBarry Smith   ISColoringValue maxcol = 0;
132747c6ae99SBarry Smith   DM_Composite    *com   = (DM_Composite*)dm->data;
132847c6ae99SBarry Smith 
132947c6ae99SBarry Smith   PetscFunctionBegin;
133047c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1331ce94432eSBarry Smith   if (ctype == IS_COLORING_GHOSTED) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only global coloring supported");
1332e3247f34SBarry Smith   else if (ctype == IS_COLORING_GLOBAL) {
133347c6ae99SBarry Smith     n = com->n;
1334ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Unknown ISColoringType");
1335785e854fSJed Brown   ierr = PetscMalloc1(n,&colors);CHKERRQ(ierr); /* freed in ISColoringDestroy() */
133647c6ae99SBarry Smith 
13370298fd71SBarry Smith   ierr = PetscOptionsGetBool(NULL,"-dmcomposite_dense_jacobian",&dense,NULL);CHKERRQ(ierr);
133847c6ae99SBarry Smith   if (dense) {
133947c6ae99SBarry Smith     for (i=0; i<n; i++) {
134047c6ae99SBarry Smith       colors[i] = (ISColoringValue)(com->rstart + i);
134147c6ae99SBarry Smith     }
134247c6ae99SBarry Smith     maxcol = com->N;
134347c6ae99SBarry Smith   } else {
134447c6ae99SBarry Smith     struct DMCompositeLink *next = com->next;
134547c6ae99SBarry Smith     PetscMPIInt            rank;
134647c6ae99SBarry Smith 
1347ce94432eSBarry Smith     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
134847c6ae99SBarry Smith     cnt  = 0;
134947c6ae99SBarry Smith     while (next) {
135047c6ae99SBarry Smith       ISColoring lcoloring;
135147c6ae99SBarry Smith 
1352b412c318SBarry Smith       ierr = DMCreateColoring(next->dm,IS_COLORING_GLOBAL,&lcoloring);CHKERRQ(ierr);
135347c6ae99SBarry Smith       for (i=0; i<lcoloring->N; i++) {
135447c6ae99SBarry Smith         colors[cnt++] = maxcol + lcoloring->colors[i];
135547c6ae99SBarry Smith       }
135647c6ae99SBarry Smith       maxcol += lcoloring->n;
1357fcfd50ebSBarry Smith       ierr    = ISColoringDestroy(&lcoloring);CHKERRQ(ierr);
135847c6ae99SBarry Smith       next    = next->next;
135947c6ae99SBarry Smith     }
136047c6ae99SBarry Smith   }
1361aaf3ff59SMatthew G. Knepley   ierr = ISColoringCreate(PetscObjectComm((PetscObject)dm),maxcol,n,colors,PETSC_OWN_POINTER,coloring);CHKERRQ(ierr);
136247c6ae99SBarry Smith   PetscFunctionReturn(0);
136347c6ae99SBarry Smith }
136447c6ae99SBarry Smith 
136547c6ae99SBarry Smith #undef __FUNCT__
13660c010503SBarry Smith #define __FUNCT__ "DMGlobalToLocalBegin_Composite"
13677087cfbeSBarry Smith PetscErrorCode  DMGlobalToLocalBegin_Composite(DM dm,Vec gvec,InsertMode mode,Vec lvec)
136847c6ae99SBarry Smith {
136947c6ae99SBarry Smith   PetscErrorCode         ierr;
137047c6ae99SBarry Smith   struct DMCompositeLink *next;
137147c6ae99SBarry Smith   PetscInt               cnt = 3;
137247c6ae99SBarry Smith   PetscMPIInt            rank;
137347c6ae99SBarry Smith   PetscScalar            *garray,*larray;
137447c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
137547c6ae99SBarry Smith 
137647c6ae99SBarry Smith   PetscFunctionBegin;
137747c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
137847c6ae99SBarry Smith   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
137947c6ae99SBarry Smith   next = com->next;
138047c6ae99SBarry Smith   if (!com->setup) {
1381d7bf68aeSBarry Smith     ierr = DMSetUp(dm);CHKERRQ(ierr);
138247c6ae99SBarry Smith   }
1383ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
138447c6ae99SBarry Smith   ierr = VecGetArray(gvec,&garray);CHKERRQ(ierr);
138547c6ae99SBarry Smith   ierr = VecGetArray(lvec,&larray);CHKERRQ(ierr);
138647c6ae99SBarry Smith 
138747c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
138847c6ae99SBarry Smith   while (next) {
138947c6ae99SBarry Smith     Vec      local,global;
139047c6ae99SBarry Smith     PetscInt N;
139147c6ae99SBarry Smith 
139247c6ae99SBarry Smith     ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
139347c6ae99SBarry Smith     ierr = VecGetLocalSize(global,&N);CHKERRQ(ierr);
139447c6ae99SBarry Smith     ierr = VecPlaceArray(global,garray);CHKERRQ(ierr);
139547c6ae99SBarry Smith     ierr = DMGetLocalVector(next->dm,&local);CHKERRQ(ierr);
139647c6ae99SBarry Smith     ierr = VecPlaceArray(local,larray);CHKERRQ(ierr);
139747c6ae99SBarry Smith     ierr = DMGlobalToLocalBegin(next->dm,global,mode,local);CHKERRQ(ierr);
139847c6ae99SBarry Smith     ierr = DMGlobalToLocalEnd(next->dm,global,mode,local);CHKERRQ(ierr);
139947c6ae99SBarry Smith     ierr = VecResetArray(global);CHKERRQ(ierr);
140047c6ae99SBarry Smith     ierr = VecResetArray(local);CHKERRQ(ierr);
140147c6ae99SBarry Smith     ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
140247c6ae99SBarry Smith     ierr = DMRestoreGlobalVector(next->dm,&local);CHKERRQ(ierr);
140347c6ae99SBarry Smith     cnt++;
140406ebdd98SJed Brown     larray += next->nlocal;
140547c6ae99SBarry Smith     next    = next->next;
140647c6ae99SBarry Smith   }
140747c6ae99SBarry Smith 
14080298fd71SBarry Smith   ierr = VecRestoreArray(gvec,NULL);CHKERRQ(ierr);
14090298fd71SBarry Smith   ierr = VecRestoreArray(lvec,NULL);CHKERRQ(ierr);
141047c6ae99SBarry Smith   PetscFunctionReturn(0);
141147c6ae99SBarry Smith }
141247c6ae99SBarry Smith 
141347c6ae99SBarry Smith #undef __FUNCT__
14140c010503SBarry Smith #define __FUNCT__ "DMGlobalToLocalEnd_Composite"
14157087cfbeSBarry Smith PetscErrorCode  DMGlobalToLocalEnd_Composite(DM dm,Vec gvec,InsertMode mode,Vec lvec)
14160c010503SBarry Smith {
14170c010503SBarry Smith   PetscFunctionBegin;
14180c010503SBarry Smith   PetscFunctionReturn(0);
14190c010503SBarry Smith }
142047c6ae99SBarry Smith 
14216ae3a549SBarry Smith /*MC
14226ae3a549SBarry Smith    DMCOMPOSITE = "composite" - A DM object that is used to manage data for a collection of DMs
14236ae3a549SBarry Smith 
14246ae3a549SBarry Smith   Level: intermediate
14256ae3a549SBarry Smith 
14261abcec8cSBarry Smith .seealso: DMType, DM, DMDACreate(), DMCreate(), DMSetType(), DMCompositeCreate()
14276ae3a549SBarry Smith M*/
14286ae3a549SBarry Smith 
14296ae3a549SBarry Smith 
1430a4121054SBarry Smith #undef __FUNCT__
1431a4121054SBarry Smith #define __FUNCT__ "DMCreate_Composite"
14328cc058d9SJed Brown PETSC_EXTERN PetscErrorCode DMCreate_Composite(DM p)
1433a4121054SBarry Smith {
1434a4121054SBarry Smith   PetscErrorCode ierr;
1435a4121054SBarry Smith   DM_Composite   *com;
1436a4121054SBarry Smith 
1437a4121054SBarry Smith   PetscFunctionBegin;
1438b00a9115SJed Brown   ierr      = PetscNewLog(p,&com);CHKERRQ(ierr);
1439a4121054SBarry Smith   p->data   = com;
1440a4121054SBarry Smith   ierr      = PetscObjectChangeTypeName((PetscObject)p,"DMComposite");CHKERRQ(ierr);
1441a4121054SBarry Smith   com->n    = 0;
14420298fd71SBarry Smith   com->next = NULL;
1443a4121054SBarry Smith   com->nDM  = 0;
1444a4121054SBarry Smith 
1445a4121054SBarry Smith   p->ops->createglobalvector              = DMCreateGlobalVector_Composite;
1446a4121054SBarry Smith   p->ops->createlocalvector               = DMCreateLocalVector_Composite;
1447184d77edSJed Brown   p->ops->getlocaltoglobalmapping         = DMGetLocalToGlobalMapping_Composite;
14484d343eeaSMatthew G Knepley   p->ops->createfieldis                   = DMCreateFieldIS_Composite;
144916621825SDmitry Karpeev   p->ops->createfielddecomposition        = DMCreateFieldDecomposition_Composite;
1450a4121054SBarry Smith   p->ops->refine                          = DMRefine_Composite;
145114354c39SJed Brown   p->ops->coarsen                         = DMCoarsen_Composite;
145225296bd5SBarry Smith   p->ops->createinterpolation             = DMCreateInterpolation_Composite;
145325296bd5SBarry Smith   p->ops->creatematrix                    = DMCreateMatrix_Composite;
1454e727c939SJed Brown   p->ops->getcoloring                     = DMCreateColoring_Composite;
1455a4121054SBarry Smith   p->ops->globaltolocalbegin              = DMGlobalToLocalBegin_Composite;
1456a4121054SBarry Smith   p->ops->globaltolocalend                = DMGlobalToLocalEnd_Composite;
1457a4121054SBarry Smith   p->ops->destroy                         = DMDestroy_Composite;
1458a4121054SBarry Smith   p->ops->view                            = DMView_Composite;
1459a4121054SBarry Smith   p->ops->setup                           = DMSetUp_Composite;
1460a4121054SBarry Smith   PetscFunctionReturn(0);
1461a4121054SBarry Smith }
1462a4121054SBarry Smith 
14630c010503SBarry Smith #undef __FUNCT__
14640c010503SBarry Smith #define __FUNCT__ "DMCompositeCreate"
14650c010503SBarry Smith /*@C
14660c010503SBarry Smith     DMCompositeCreate - Creates a vector packer, used to generate "composite"
14670c010503SBarry Smith       vectors made up of several subvectors.
14680c010503SBarry Smith 
14690c010503SBarry Smith     Collective on MPI_Comm
147047c6ae99SBarry Smith 
147147c6ae99SBarry Smith     Input Parameter:
14720c010503SBarry Smith .   comm - the processors that will share the global vector
14730c010503SBarry Smith 
14740c010503SBarry Smith     Output Parameters:
14750c010503SBarry Smith .   packer - the packer object
147647c6ae99SBarry Smith 
147747c6ae99SBarry Smith     Level: advanced
147847c6ae99SBarry Smith 
14791abcec8cSBarry Smith .seealso DMDestroy(), DMCompositeAddDM(), DMCompositeScatter(), DMCOMPOSITE,DMCreate()
14806eb61c8cSJed Brown          DMCompositeGather(), DMCreateGlobalVector(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess()
148147c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
148247c6ae99SBarry Smith 
148347c6ae99SBarry Smith @*/
14847087cfbeSBarry Smith PetscErrorCode  DMCompositeCreate(MPI_Comm comm,DM *packer)
148547c6ae99SBarry Smith {
14860c010503SBarry Smith   PetscErrorCode ierr;
14870c010503SBarry Smith 
148847c6ae99SBarry Smith   PetscFunctionBegin;
14890c010503SBarry Smith   PetscValidPointer(packer,2);
1490a4121054SBarry Smith   ierr = DMCreate(comm,packer);CHKERRQ(ierr);
1491a4121054SBarry Smith   ierr = DMSetType(*packer,DMCOMPOSITE);CHKERRQ(ierr);
149247c6ae99SBarry Smith   PetscFunctionReturn(0);
149347c6ae99SBarry Smith }
1494