xref: /petsc/src/dm/impls/composite/pack.c (revision f3cb0f7e1227ff5d3f524be576d0c3f8ebba9e5d)
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
10bebe2cf6SSatish 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 
905*f3cb0f7eSJed Brown     Fortran Notes:
906*f3cb0f7eSJed Brown 
907*f3cb0f7eSJed Brown        The output argument 'is' must be an allocated array of sufficient length, which can be learned using DMCompositeGetNumberDM().
908*f3cb0f7eSJed Brown 
9099ae5db72SJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
91047c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetAccess(), DMCompositeScatter(),
91147c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(),DMCompositeGetEntries()
91247c6ae99SBarry Smith 
91347c6ae99SBarry Smith @*/
9147087cfbeSBarry Smith PetscErrorCode  DMCompositeGetGlobalISs(DM dm,IS *is[])
91547c6ae99SBarry Smith {
91647c6ae99SBarry Smith   PetscErrorCode         ierr;
91766bb578eSMark Adams   PetscInt               cnt = 0;
91847c6ae99SBarry Smith   struct DMCompositeLink *next;
91947c6ae99SBarry Smith   PetscMPIInt            rank;
92047c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
92147c6ae99SBarry Smith 
92247c6ae99SBarry Smith   PetscFunctionBegin;
92347c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
924854ce69bSBarry Smith   ierr = PetscMalloc1(com->nDM,is);CHKERRQ(ierr);
92547c6ae99SBarry Smith   next = com->next;
926ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
92747c6ae99SBarry Smith 
92847c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
92947c6ae99SBarry Smith   while (next) {
93066bb578eSMark Adams     ierr = ISCreateStride(PetscObjectComm((PetscObject)dm),next->n,next->grstart,1,&(*is)[cnt]);CHKERRQ(ierr);
9310f21e855SMatthew G. Knepley     if (dm->prob) {
93265c226d8SMatthew G. Knepley       MatNullSpace space;
93365c226d8SMatthew G. Knepley       Mat          pmat;
9340f21e855SMatthew G. Knepley       PetscObject  disc;
9350f21e855SMatthew G. Knepley       PetscInt     Nf;
93665c226d8SMatthew G. Knepley 
9372764a2aaSMatthew G. Knepley       ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr);
938f24dd8d2SMatthew G. Knepley       if (cnt < Nf) {
9392764a2aaSMatthew G. Knepley         ierr = PetscDSGetDiscretization(dm->prob, cnt, &disc);CHKERRQ(ierr);
9400f21e855SMatthew G. Knepley         ierr = PetscObjectQuery(disc, "nullspace", (PetscObject*) &space);CHKERRQ(ierr);
941aac2dd2dSMatthew G. Knepley         if (space) {ierr = PetscObjectCompose((PetscObject) (*is)[cnt], "nullspace", (PetscObject) space);CHKERRQ(ierr);}
9420f21e855SMatthew G. Knepley         ierr = PetscObjectQuery(disc, "nearnullspace", (PetscObject*) &space);CHKERRQ(ierr);
943aac2dd2dSMatthew G. Knepley         if (space) {ierr = PetscObjectCompose((PetscObject) (*is)[cnt], "nearnullspace", (PetscObject) space);CHKERRQ(ierr);}
9440f21e855SMatthew G. Knepley         ierr = PetscObjectQuery(disc, "pmat", (PetscObject*) &pmat);CHKERRQ(ierr);
945aac2dd2dSMatthew G. Knepley         if (pmat) {ierr = PetscObjectCompose((PetscObject) (*is)[cnt], "pmat", (PetscObject) pmat);CHKERRQ(ierr);}
94665c226d8SMatthew G. Knepley       }
947f24dd8d2SMatthew G. Knepley     }
94847c6ae99SBarry Smith     cnt++;
94947c6ae99SBarry Smith     next = next->next;
95047c6ae99SBarry Smith   }
95147c6ae99SBarry Smith   PetscFunctionReturn(0);
95247c6ae99SBarry Smith }
95347c6ae99SBarry Smith 
9544d343eeaSMatthew G Knepley #undef __FUNCT__
9554d343eeaSMatthew G Knepley #define __FUNCT__ "DMCreateFieldIS_Composite"
95621c9b008SJed Brown PetscErrorCode DMCreateFieldIS_Composite(DM dm, PetscInt *numFields,char ***fieldNames, IS **fields)
9574d343eeaSMatthew G Knepley {
9584d343eeaSMatthew G Knepley   PetscInt       nDM;
9594d343eeaSMatthew G Knepley   DM             *dms;
9604d343eeaSMatthew G Knepley   PetscInt       i;
9614d343eeaSMatthew G Knepley   PetscErrorCode ierr;
9624d343eeaSMatthew G Knepley 
9634d343eeaSMatthew G Knepley   PetscFunctionBegin;
9644d343eeaSMatthew G Knepley   ierr = DMCompositeGetNumberDM(dm, &nDM);CHKERRQ(ierr);
9658865f1eaSKarl Rupp   if (numFields) *numFields = nDM;
9664d343eeaSMatthew G Knepley   ierr = DMCompositeGetGlobalISs(dm, fields);CHKERRQ(ierr);
9674d343eeaSMatthew G Knepley   if (fieldNames) {
968785e854fSJed Brown     ierr = PetscMalloc1(nDM, &dms);CHKERRQ(ierr);
969785e854fSJed Brown     ierr = PetscMalloc1(nDM, fieldNames);CHKERRQ(ierr);
9704d343eeaSMatthew G Knepley     ierr = DMCompositeGetEntriesArray(dm, dms);CHKERRQ(ierr);
9714d343eeaSMatthew G Knepley     for (i=0; i<nDM; i++) {
9724d343eeaSMatthew G Knepley       char       buf[256];
9734d343eeaSMatthew G Knepley       const char *splitname;
9744d343eeaSMatthew G Knepley 
9754d343eeaSMatthew G Knepley       /* Split naming precedence: object name, prefix, number */
9764d343eeaSMatthew G Knepley       splitname = ((PetscObject) dm)->name;
9774d343eeaSMatthew G Knepley       if (!splitname) {
9784d343eeaSMatthew G Knepley         ierr = PetscObjectGetOptionsPrefix((PetscObject)dms[i],&splitname);CHKERRQ(ierr);
9794d343eeaSMatthew G Knepley         if (splitname) {
9804d343eeaSMatthew G Knepley           size_t len;
9818caf3d72SBarry Smith           ierr                 = PetscStrncpy(buf,splitname,sizeof(buf));CHKERRQ(ierr);
9828caf3d72SBarry Smith           buf[sizeof(buf) - 1] = 0;
9834d343eeaSMatthew G Knepley           ierr                 = PetscStrlen(buf,&len);CHKERRQ(ierr);
9844d343eeaSMatthew G Knepley           if (buf[len-1] == '_') buf[len-1] = 0; /* Remove trailing underscore if it was used */
9854d343eeaSMatthew G Knepley           splitname = buf;
9864d343eeaSMatthew G Knepley         }
9874d343eeaSMatthew G Knepley       }
9884d343eeaSMatthew G Knepley       if (!splitname) {
9898caf3d72SBarry Smith         ierr      = PetscSNPrintf(buf,sizeof(buf),"%D",i);CHKERRQ(ierr);
9904d343eeaSMatthew G Knepley         splitname = buf;
9914d343eeaSMatthew G Knepley       }
99221c9b008SJed Brown       ierr = PetscStrallocpy(splitname,&(*fieldNames)[i]);CHKERRQ(ierr);
9934d343eeaSMatthew G Knepley     }
9944d343eeaSMatthew G Knepley     ierr = PetscFree(dms);CHKERRQ(ierr);
9954d343eeaSMatthew G Knepley   }
9964d343eeaSMatthew G Knepley   PetscFunctionReturn(0);
9974d343eeaSMatthew G Knepley }
9984d343eeaSMatthew G Knepley 
999e7c4fc90SDmitry Karpeev /*
1000e7c4fc90SDmitry Karpeev  This could take over from DMCreateFieldIS(), as it is more general,
10010298fd71SBarry Smith  making DMCreateFieldIS() a special case -- calling with dmlist == NULL;
1002e7c4fc90SDmitry Karpeev  At this point it's probably best to be less intrusive, however.
1003e7c4fc90SDmitry Karpeev  */
1004e7c4fc90SDmitry Karpeev #undef __FUNCT__
100516621825SDmitry Karpeev #define __FUNCT__ "DMCreateFieldDecomposition_Composite"
100616621825SDmitry Karpeev PetscErrorCode DMCreateFieldDecomposition_Composite(DM dm, PetscInt *len,char ***namelist, IS **islist, DM **dmlist)
1007e7c4fc90SDmitry Karpeev {
1008e7c4fc90SDmitry Karpeev   PetscInt       nDM;
1009e7c4fc90SDmitry Karpeev   PetscInt       i;
1010e7c4fc90SDmitry Karpeev   PetscErrorCode ierr;
1011e7c4fc90SDmitry Karpeev 
1012e7c4fc90SDmitry Karpeev   PetscFunctionBegin;
1013e7c4fc90SDmitry Karpeev   ierr = DMCreateFieldIS_Composite(dm, len, namelist, islist);CHKERRQ(ierr);
1014e7c4fc90SDmitry Karpeev   if (dmlist) {
1015e7c4fc90SDmitry Karpeev     ierr = DMCompositeGetNumberDM(dm, &nDM);CHKERRQ(ierr);
1016785e854fSJed Brown     ierr = PetscMalloc1(nDM, dmlist);CHKERRQ(ierr);
1017e7c4fc90SDmitry Karpeev     ierr = DMCompositeGetEntriesArray(dm, *dmlist);CHKERRQ(ierr);
1018e7c4fc90SDmitry Karpeev     for (i=0; i<nDM; i++) {
1019e7c4fc90SDmitry Karpeev       ierr = PetscObjectReference((PetscObject)((*dmlist)[i]));CHKERRQ(ierr);
1020e7c4fc90SDmitry Karpeev     }
1021e7c4fc90SDmitry Karpeev   }
1022e7c4fc90SDmitry Karpeev   PetscFunctionReturn(0);
1023e7c4fc90SDmitry Karpeev }
1024e7c4fc90SDmitry Karpeev 
1025e7c4fc90SDmitry Karpeev 
1026e7c4fc90SDmitry Karpeev 
102747c6ae99SBarry Smith /* -------------------------------------------------------------------------------------*/
102847c6ae99SBarry Smith #undef __FUNCT__
102947c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetLocalVectors"
103047c6ae99SBarry Smith /*@C
10319ae5db72SJed Brown     DMCompositeGetLocalVectors - Gets local vectors for each part of a DMComposite.
103247c6ae99SBarry Smith        Use DMCompositeRestoreLocalVectors() to return them.
103347c6ae99SBarry Smith 
103447c6ae99SBarry Smith     Not Collective
103547c6ae99SBarry Smith 
103647c6ae99SBarry Smith     Input Parameter:
103747c6ae99SBarry Smith .    dm - the packer object
103847c6ae99SBarry Smith 
103947c6ae99SBarry Smith     Output Parameter:
10409ae5db72SJed Brown .   Vec ... - the individual sequential Vecs
104147c6ae99SBarry Smith 
104247c6ae99SBarry Smith     Level: advanced
104347c6ae99SBarry Smith 
10449ae5db72SJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
10456eb61c8cSJed Brown          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
104647c6ae99SBarry Smith          DMCompositeRestoreLocalVectors(), DMCompositeScatter(), DMCompositeGetEntries()
104747c6ae99SBarry Smith 
104847c6ae99SBarry Smith @*/
10497087cfbeSBarry Smith PetscErrorCode  DMCompositeGetLocalVectors(DM dm,...)
105047c6ae99SBarry Smith {
105147c6ae99SBarry Smith   va_list                Argp;
105247c6ae99SBarry Smith   PetscErrorCode         ierr;
105347c6ae99SBarry Smith   struct DMCompositeLink *next;
105447c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
105547c6ae99SBarry Smith 
105647c6ae99SBarry Smith   PetscFunctionBegin;
105747c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
105847c6ae99SBarry Smith   next = com->next;
105947c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
106047c6ae99SBarry Smith   va_start(Argp,dm);
106147c6ae99SBarry Smith   while (next) {
106247c6ae99SBarry Smith     Vec *vec;
106347c6ae99SBarry Smith     vec = va_arg(Argp, Vec*);
106406930112SJed Brown     if (vec) {ierr = DMGetLocalVector(next->dm,vec);CHKERRQ(ierr);}
106547c6ae99SBarry Smith     next = next->next;
106647c6ae99SBarry Smith   }
106747c6ae99SBarry Smith   va_end(Argp);
106847c6ae99SBarry Smith   PetscFunctionReturn(0);
106947c6ae99SBarry Smith }
107047c6ae99SBarry Smith 
107147c6ae99SBarry Smith #undef __FUNCT__
107247c6ae99SBarry Smith #define __FUNCT__ "DMCompositeRestoreLocalVectors"
107347c6ae99SBarry Smith /*@C
10749ae5db72SJed Brown     DMCompositeRestoreLocalVectors - Restores local vectors for each part of a DMComposite.
107547c6ae99SBarry Smith 
107647c6ae99SBarry Smith     Not Collective
107747c6ae99SBarry Smith 
107847c6ae99SBarry Smith     Input Parameter:
107947c6ae99SBarry Smith .    dm - the packer object
108047c6ae99SBarry Smith 
108147c6ae99SBarry Smith     Output Parameter:
10829ae5db72SJed Brown .   Vec ... - the individual sequential Vecs
108347c6ae99SBarry Smith 
108447c6ae99SBarry Smith     Level: advanced
108547c6ae99SBarry Smith 
10869ae5db72SJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
10876eb61c8cSJed Brown          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
108847c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeScatter(), DMCompositeGetEntries()
108947c6ae99SBarry Smith 
109047c6ae99SBarry Smith @*/
10917087cfbeSBarry Smith PetscErrorCode  DMCompositeRestoreLocalVectors(DM dm,...)
109247c6ae99SBarry Smith {
109347c6ae99SBarry Smith   va_list                Argp;
109447c6ae99SBarry Smith   PetscErrorCode         ierr;
109547c6ae99SBarry Smith   struct DMCompositeLink *next;
109647c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
109747c6ae99SBarry Smith 
109847c6ae99SBarry Smith   PetscFunctionBegin;
109947c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
110047c6ae99SBarry Smith   next = com->next;
110147c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
110247c6ae99SBarry Smith   va_start(Argp,dm);
110347c6ae99SBarry Smith   while (next) {
110447c6ae99SBarry Smith     Vec *vec;
110547c6ae99SBarry Smith     vec = va_arg(Argp, Vec*);
110606930112SJed Brown     if (vec) {ierr = DMRestoreLocalVector(next->dm,vec);CHKERRQ(ierr);}
110747c6ae99SBarry Smith     next = next->next;
110847c6ae99SBarry Smith   }
110947c6ae99SBarry Smith   va_end(Argp);
111047c6ae99SBarry Smith   PetscFunctionReturn(0);
111147c6ae99SBarry Smith }
111247c6ae99SBarry Smith 
111347c6ae99SBarry Smith /* -------------------------------------------------------------------------------------*/
111447c6ae99SBarry Smith #undef __FUNCT__
111547c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetEntries"
111647c6ae99SBarry Smith /*@C
11179ae5db72SJed Brown     DMCompositeGetEntries - Gets the DM for each entry in a DMComposite.
111847c6ae99SBarry Smith 
111947c6ae99SBarry Smith     Not Collective
112047c6ae99SBarry Smith 
112147c6ae99SBarry Smith     Input Parameter:
112247c6ae99SBarry Smith .    dm - the packer object
112347c6ae99SBarry Smith 
112447c6ae99SBarry Smith     Output Parameter:
11259ae5db72SJed Brown .   DM ... - the individual entries (DMs)
112647c6ae99SBarry Smith 
112747c6ae99SBarry Smith     Level: advanced
112847c6ae99SBarry Smith 
11292fa5ba8aSJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(), DMCompositeGetEntriesArray()
11306eb61c8cSJed Brown          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
113147c6ae99SBarry Smith          DMCompositeRestoreLocalVectors(), DMCompositeGetLocalVectors(),  DMCompositeScatter(),
113247c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors()
113347c6ae99SBarry Smith 
113447c6ae99SBarry Smith @*/
11357087cfbeSBarry Smith PetscErrorCode  DMCompositeGetEntries(DM dm,...)
113647c6ae99SBarry Smith {
113747c6ae99SBarry Smith   va_list                Argp;
113847c6ae99SBarry Smith   struct DMCompositeLink *next;
113947c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
114047c6ae99SBarry Smith 
114147c6ae99SBarry Smith   PetscFunctionBegin;
114247c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
114347c6ae99SBarry Smith   next = com->next;
114447c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
114547c6ae99SBarry Smith   va_start(Argp,dm);
114647c6ae99SBarry Smith   while (next) {
114747c6ae99SBarry Smith     DM *dmn;
114847c6ae99SBarry Smith     dmn = va_arg(Argp, DM*);
11499ae5db72SJed Brown     if (dmn) *dmn = next->dm;
115047c6ae99SBarry Smith     next = next->next;
115147c6ae99SBarry Smith   }
115247c6ae99SBarry Smith   va_end(Argp);
115347c6ae99SBarry Smith   PetscFunctionReturn(0);
115447c6ae99SBarry Smith }
115547c6ae99SBarry Smith 
115647c6ae99SBarry Smith #undef __FUNCT__
11572fa5ba8aSJed Brown #define __FUNCT__ "DMCompositeGetEntriesArray"
1158dbab29e1SMark F. Adams /*@C
11592fa5ba8aSJed Brown     DMCompositeGetEntriesArray - Gets the DM for each entry in a DMComposite.
11602fa5ba8aSJed Brown 
11612fa5ba8aSJed Brown     Not Collective
11622fa5ba8aSJed Brown 
11632fa5ba8aSJed Brown     Input Parameter:
1164907376e6SBarry Smith .    dm - the packer object
1165907376e6SBarry Smith 
1166907376e6SBarry Smith     Output Parameter:
1167907376e6SBarry Smith .    dms - array of sufficient length (see DMCompositeGetNumberDM()) to hold the individual DMs
11682fa5ba8aSJed Brown 
11692fa5ba8aSJed Brown     Level: advanced
11702fa5ba8aSJed Brown 
11712fa5ba8aSJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(), DMCompositeGetEntries()
11722fa5ba8aSJed Brown          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
11732fa5ba8aSJed Brown          DMCompositeRestoreLocalVectors(), DMCompositeGetLocalVectors(),  DMCompositeScatter(),
11742fa5ba8aSJed Brown          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors()
11752fa5ba8aSJed Brown 
11762fa5ba8aSJed Brown @*/
11772fa5ba8aSJed Brown PetscErrorCode DMCompositeGetEntriesArray(DM dm,DM dms[])
11782fa5ba8aSJed Brown {
11792fa5ba8aSJed Brown   struct DMCompositeLink *next;
11802fa5ba8aSJed Brown   DM_Composite           *com = (DM_Composite*)dm->data;
11812fa5ba8aSJed Brown   PetscInt               i;
11822fa5ba8aSJed Brown 
11832fa5ba8aSJed Brown   PetscFunctionBegin;
11842fa5ba8aSJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
11852fa5ba8aSJed Brown   /* loop over packed objects, handling one at at time */
11862fa5ba8aSJed Brown   for (next=com->next,i=0; next; next=next->next,i++) dms[i] = next->dm;
11872fa5ba8aSJed Brown   PetscFunctionReturn(0);
11882fa5ba8aSJed Brown }
11892fa5ba8aSJed Brown 
11902fa5ba8aSJed Brown #undef __FUNCT__
11910c010503SBarry Smith #define __FUNCT__ "DMRefine_Composite"
11927087cfbeSBarry Smith PetscErrorCode  DMRefine_Composite(DM dmi,MPI_Comm comm,DM *fine)
119347c6ae99SBarry Smith {
119447c6ae99SBarry Smith   PetscErrorCode         ierr;
119547c6ae99SBarry Smith   struct DMCompositeLink *next;
119647c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dmi->data;
119747c6ae99SBarry Smith   DM                     dm;
119847c6ae99SBarry Smith 
119947c6ae99SBarry Smith   PetscFunctionBegin;
120047c6ae99SBarry Smith   PetscValidHeaderSpecific(dmi,DM_CLASSID,1);
1201ce94432eSBarry Smith   if (comm == MPI_COMM_NULL) {
1202ce94432eSBarry Smith     ierr = PetscObjectGetComm((PetscObject)dmi,&comm);CHKERRQ(ierr);
1203ce94432eSBarry Smith   }
12042ce3a92bSJed Brown   ierr = DMSetUp(dmi);CHKERRQ(ierr);
120547c6ae99SBarry Smith   next = com->next;
120647c6ae99SBarry Smith   ierr = DMCompositeCreate(comm,fine);CHKERRQ(ierr);
120747c6ae99SBarry Smith 
120847c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
120947c6ae99SBarry Smith   while (next) {
121047c6ae99SBarry Smith     ierr = DMRefine(next->dm,comm,&dm);CHKERRQ(ierr);
121147c6ae99SBarry Smith     ierr = DMCompositeAddDM(*fine,dm);CHKERRQ(ierr);
121247c6ae99SBarry Smith     ierr = PetscObjectDereference((PetscObject)dm);CHKERRQ(ierr);
121347c6ae99SBarry Smith     next = next->next;
121447c6ae99SBarry Smith   }
121547c6ae99SBarry Smith   PetscFunctionReturn(0);
121647c6ae99SBarry Smith }
121747c6ae99SBarry Smith 
121814354c39SJed Brown #undef __FUNCT__
121914354c39SJed Brown #define __FUNCT__ "DMCoarsen_Composite"
122014354c39SJed Brown PetscErrorCode  DMCoarsen_Composite(DM dmi,MPI_Comm comm,DM *fine)
122114354c39SJed Brown {
122214354c39SJed Brown   PetscErrorCode         ierr;
122314354c39SJed Brown   struct DMCompositeLink *next;
122414354c39SJed Brown   DM_Composite           *com = (DM_Composite*)dmi->data;
122514354c39SJed Brown   DM                     dm;
122614354c39SJed Brown 
122714354c39SJed Brown   PetscFunctionBegin;
122814354c39SJed Brown   PetscValidHeaderSpecific(dmi,DM_CLASSID,1);
12292ce3a92bSJed Brown   ierr = DMSetUp(dmi);CHKERRQ(ierr);
12302ee06e3bSJed Brown   if (comm == MPI_COMM_NULL) {
123125296bd5SBarry Smith     ierr = PetscObjectGetComm((PetscObject)dmi,&comm);CHKERRQ(ierr);
123225296bd5SBarry Smith   }
123314354c39SJed Brown   next = com->next;
123414354c39SJed Brown   ierr = DMCompositeCreate(comm,fine);CHKERRQ(ierr);
123514354c39SJed Brown 
123614354c39SJed Brown   /* loop over packed objects, handling one at at time */
123714354c39SJed Brown   while (next) {
123814354c39SJed Brown     ierr = DMCoarsen(next->dm,comm,&dm);CHKERRQ(ierr);
123914354c39SJed Brown     ierr = DMCompositeAddDM(*fine,dm);CHKERRQ(ierr);
124014354c39SJed Brown     ierr = PetscObjectDereference((PetscObject)dm);CHKERRQ(ierr);
124114354c39SJed Brown     next = next->next;
124214354c39SJed Brown   }
124314354c39SJed Brown   PetscFunctionReturn(0);
124414354c39SJed Brown }
124547c6ae99SBarry Smith 
124647c6ae99SBarry Smith #undef __FUNCT__
1247e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_Composite"
1248e727c939SJed Brown PetscErrorCode  DMCreateInterpolation_Composite(DM coarse,DM fine,Mat *A,Vec *v)
124947c6ae99SBarry Smith {
125047c6ae99SBarry Smith   PetscErrorCode         ierr;
12519ae5db72SJed Brown   PetscInt               m,n,M,N,nDM,i;
125247c6ae99SBarry Smith   struct DMCompositeLink *nextc;
125347c6ae99SBarry Smith   struct DMCompositeLink *nextf;
125425296bd5SBarry Smith   Vec                    gcoarse,gfine,*vecs;
125547c6ae99SBarry Smith   DM_Composite           *comcoarse = (DM_Composite*)coarse->data;
125647c6ae99SBarry Smith   DM_Composite           *comfine   = (DM_Composite*)fine->data;
12579ae5db72SJed Brown   Mat                    *mats;
125847c6ae99SBarry Smith 
125947c6ae99SBarry Smith   PetscFunctionBegin;
126047c6ae99SBarry Smith   PetscValidHeaderSpecific(coarse,DM_CLASSID,1);
126147c6ae99SBarry Smith   PetscValidHeaderSpecific(fine,DM_CLASSID,2);
1262f692024eSJed Brown   ierr = DMSetUp(coarse);CHKERRQ(ierr);
1263f692024eSJed Brown   ierr = DMSetUp(fine);CHKERRQ(ierr);
126447c6ae99SBarry Smith   /* use global vectors only for determining matrix layout */
12659ae5db72SJed Brown   ierr = DMGetGlobalVector(coarse,&gcoarse);CHKERRQ(ierr);
12669ae5db72SJed Brown   ierr = DMGetGlobalVector(fine,&gfine);CHKERRQ(ierr);
126747c6ae99SBarry Smith   ierr = VecGetLocalSize(gcoarse,&n);CHKERRQ(ierr);
126847c6ae99SBarry Smith   ierr = VecGetLocalSize(gfine,&m);CHKERRQ(ierr);
126947c6ae99SBarry Smith   ierr = VecGetSize(gcoarse,&N);CHKERRQ(ierr);
127047c6ae99SBarry Smith   ierr = VecGetSize(gfine,&M);CHKERRQ(ierr);
12719ae5db72SJed Brown   ierr = DMRestoreGlobalVector(coarse,&gcoarse);CHKERRQ(ierr);
12729ae5db72SJed Brown   ierr = DMRestoreGlobalVector(fine,&gfine);CHKERRQ(ierr);
127347c6ae99SBarry Smith 
12749ae5db72SJed Brown   nDM = comfine->nDM;
1275ce94432eSBarry 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);
12761795a4d1SJed Brown   ierr = PetscCalloc1(nDM*nDM,&mats);CHKERRQ(ierr);
127725296bd5SBarry Smith   if (v) {
12781795a4d1SJed Brown     ierr = PetscCalloc1(nDM,&vecs);CHKERRQ(ierr);
127925296bd5SBarry Smith   }
128047c6ae99SBarry Smith 
128147c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
12829ae5db72SJed Brown   for (nextc=comcoarse->next,nextf=comfine->next,i=0; nextc; nextc=nextc->next,nextf=nextf->next,i++) {
128325296bd5SBarry Smith     if (!v) {
12840298fd71SBarry Smith       ierr = DMCreateInterpolation(nextc->dm,nextf->dm,&mats[i*nDM+i],NULL);CHKERRQ(ierr);
128525296bd5SBarry Smith     } else {
128625296bd5SBarry Smith       ierr = DMCreateInterpolation(nextc->dm,nextf->dm,&mats[i*nDM+i],&vecs[i]);CHKERRQ(ierr);
128725296bd5SBarry Smith     }
128847c6ae99SBarry Smith   }
1289ce94432eSBarry Smith   ierr = MatCreateNest(PetscObjectComm((PetscObject)fine),nDM,NULL,nDM,NULL,mats,A);CHKERRQ(ierr);
129025296bd5SBarry Smith   if (v) {
1291ce94432eSBarry Smith     ierr = VecCreateNest(PetscObjectComm((PetscObject)fine),nDM,NULL,vecs,v);CHKERRQ(ierr);
129225296bd5SBarry Smith   }
12939ae5db72SJed Brown   for (i=0; i<nDM*nDM; i++) {ierr = MatDestroy(&mats[i]);CHKERRQ(ierr);}
12949ae5db72SJed Brown   ierr = PetscFree(mats);CHKERRQ(ierr);
129525296bd5SBarry Smith   if (v) {
129625296bd5SBarry Smith     for (i=0; i<nDM; i++) {ierr = VecDestroy(&vecs[i]);CHKERRQ(ierr);}
129725296bd5SBarry Smith     ierr = PetscFree(vecs);CHKERRQ(ierr);
129825296bd5SBarry Smith   }
129947c6ae99SBarry Smith   PetscFunctionReturn(0);
130047c6ae99SBarry Smith }
130147c6ae99SBarry Smith 
130247c6ae99SBarry Smith #undef __FUNCT__
1303184d77edSJed Brown #define __FUNCT__ "DMGetLocalToGlobalMapping_Composite"
1304184d77edSJed Brown static PetscErrorCode DMGetLocalToGlobalMapping_Composite(DM dm)
13051411c6eeSJed Brown {
13061411c6eeSJed Brown   DM_Composite           *com = (DM_Composite*)dm->data;
13071411c6eeSJed Brown   ISLocalToGlobalMapping *ltogs;
1308f7efa3c7SJed Brown   PetscInt               i;
13091411c6eeSJed Brown   PetscErrorCode         ierr;
13101411c6eeSJed Brown 
13111411c6eeSJed Brown   PetscFunctionBegin;
13121411c6eeSJed Brown   /* Set the ISLocalToGlobalMapping on the new matrix */
13131411c6eeSJed Brown   ierr = DMCompositeGetISLocalToGlobalMappings(dm,&ltogs);CHKERRQ(ierr);
1314ce94432eSBarry Smith   ierr = ISLocalToGlobalMappingConcatenate(PetscObjectComm((PetscObject)dm),com->nDM,ltogs,&dm->ltogmap);CHKERRQ(ierr);
13159ae5db72SJed Brown   for (i=0; i<com->nDM; i++) {ierr = ISLocalToGlobalMappingDestroy(&ltogs[i]);CHKERRQ(ierr);}
13161411c6eeSJed Brown   ierr = PetscFree(ltogs);CHKERRQ(ierr);
13171411c6eeSJed Brown   PetscFunctionReturn(0);
13181411c6eeSJed Brown }
13191411c6eeSJed Brown 
13201411c6eeSJed Brown 
13211411c6eeSJed Brown #undef __FUNCT__
1322e727c939SJed Brown #define __FUNCT__ "DMCreateColoring_Composite"
1323b412c318SBarry Smith PetscErrorCode  DMCreateColoring_Composite(DM dm,ISColoringType ctype,ISColoring *coloring)
132447c6ae99SBarry Smith {
132547c6ae99SBarry Smith   PetscErrorCode  ierr;
132647c6ae99SBarry Smith   PetscInt        n,i,cnt;
132747c6ae99SBarry Smith   ISColoringValue *colors;
132847c6ae99SBarry Smith   PetscBool       dense  = PETSC_FALSE;
132947c6ae99SBarry Smith   ISColoringValue maxcol = 0;
133047c6ae99SBarry Smith   DM_Composite    *com   = (DM_Composite*)dm->data;
133147c6ae99SBarry Smith 
133247c6ae99SBarry Smith   PetscFunctionBegin;
133347c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1334ce94432eSBarry Smith   if (ctype == IS_COLORING_GHOSTED) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only global coloring supported");
1335e3247f34SBarry Smith   else if (ctype == IS_COLORING_GLOBAL) {
133647c6ae99SBarry Smith     n = com->n;
1337ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Unknown ISColoringType");
1338785e854fSJed Brown   ierr = PetscMalloc1(n,&colors);CHKERRQ(ierr); /* freed in ISColoringDestroy() */
133947c6ae99SBarry Smith 
13400298fd71SBarry Smith   ierr = PetscOptionsGetBool(NULL,"-dmcomposite_dense_jacobian",&dense,NULL);CHKERRQ(ierr);
134147c6ae99SBarry Smith   if (dense) {
134247c6ae99SBarry Smith     for (i=0; i<n; i++) {
134347c6ae99SBarry Smith       colors[i] = (ISColoringValue)(com->rstart + i);
134447c6ae99SBarry Smith     }
134547c6ae99SBarry Smith     maxcol = com->N;
134647c6ae99SBarry Smith   } else {
134747c6ae99SBarry Smith     struct DMCompositeLink *next = com->next;
134847c6ae99SBarry Smith     PetscMPIInt            rank;
134947c6ae99SBarry Smith 
1350ce94432eSBarry Smith     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
135147c6ae99SBarry Smith     cnt  = 0;
135247c6ae99SBarry Smith     while (next) {
135347c6ae99SBarry Smith       ISColoring lcoloring;
135447c6ae99SBarry Smith 
1355b412c318SBarry Smith       ierr = DMCreateColoring(next->dm,IS_COLORING_GLOBAL,&lcoloring);CHKERRQ(ierr);
135647c6ae99SBarry Smith       for (i=0; i<lcoloring->N; i++) {
135747c6ae99SBarry Smith         colors[cnt++] = maxcol + lcoloring->colors[i];
135847c6ae99SBarry Smith       }
135947c6ae99SBarry Smith       maxcol += lcoloring->n;
1360fcfd50ebSBarry Smith       ierr    = ISColoringDestroy(&lcoloring);CHKERRQ(ierr);
136147c6ae99SBarry Smith       next    = next->next;
136247c6ae99SBarry Smith     }
136347c6ae99SBarry Smith   }
1364aaf3ff59SMatthew G. Knepley   ierr = ISColoringCreate(PetscObjectComm((PetscObject)dm),maxcol,n,colors,PETSC_OWN_POINTER,coloring);CHKERRQ(ierr);
136547c6ae99SBarry Smith   PetscFunctionReturn(0);
136647c6ae99SBarry Smith }
136747c6ae99SBarry Smith 
136847c6ae99SBarry Smith #undef __FUNCT__
13690c010503SBarry Smith #define __FUNCT__ "DMGlobalToLocalBegin_Composite"
13707087cfbeSBarry Smith PetscErrorCode  DMGlobalToLocalBegin_Composite(DM dm,Vec gvec,InsertMode mode,Vec lvec)
137147c6ae99SBarry Smith {
137247c6ae99SBarry Smith   PetscErrorCode         ierr;
137347c6ae99SBarry Smith   struct DMCompositeLink *next;
137447c6ae99SBarry Smith   PetscInt               cnt = 3;
137547c6ae99SBarry Smith   PetscMPIInt            rank;
137647c6ae99SBarry Smith   PetscScalar            *garray,*larray;
137747c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
137847c6ae99SBarry Smith 
137947c6ae99SBarry Smith   PetscFunctionBegin;
138047c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
138147c6ae99SBarry Smith   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
138247c6ae99SBarry Smith   next = com->next;
138347c6ae99SBarry Smith   if (!com->setup) {
1384d7bf68aeSBarry Smith     ierr = DMSetUp(dm);CHKERRQ(ierr);
138547c6ae99SBarry Smith   }
1386ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
138747c6ae99SBarry Smith   ierr = VecGetArray(gvec,&garray);CHKERRQ(ierr);
138847c6ae99SBarry Smith   ierr = VecGetArray(lvec,&larray);CHKERRQ(ierr);
138947c6ae99SBarry Smith 
139047c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
139147c6ae99SBarry Smith   while (next) {
139247c6ae99SBarry Smith     Vec      local,global;
139347c6ae99SBarry Smith     PetscInt N;
139447c6ae99SBarry Smith 
139547c6ae99SBarry Smith     ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
139647c6ae99SBarry Smith     ierr = VecGetLocalSize(global,&N);CHKERRQ(ierr);
139747c6ae99SBarry Smith     ierr = VecPlaceArray(global,garray);CHKERRQ(ierr);
139847c6ae99SBarry Smith     ierr = DMGetLocalVector(next->dm,&local);CHKERRQ(ierr);
139947c6ae99SBarry Smith     ierr = VecPlaceArray(local,larray);CHKERRQ(ierr);
140047c6ae99SBarry Smith     ierr = DMGlobalToLocalBegin(next->dm,global,mode,local);CHKERRQ(ierr);
140147c6ae99SBarry Smith     ierr = DMGlobalToLocalEnd(next->dm,global,mode,local);CHKERRQ(ierr);
140247c6ae99SBarry Smith     ierr = VecResetArray(global);CHKERRQ(ierr);
140347c6ae99SBarry Smith     ierr = VecResetArray(local);CHKERRQ(ierr);
140447c6ae99SBarry Smith     ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
140547c6ae99SBarry Smith     ierr = DMRestoreGlobalVector(next->dm,&local);CHKERRQ(ierr);
140647c6ae99SBarry Smith     cnt++;
140706ebdd98SJed Brown     larray += next->nlocal;
140847c6ae99SBarry Smith     next    = next->next;
140947c6ae99SBarry Smith   }
141047c6ae99SBarry Smith 
14110298fd71SBarry Smith   ierr = VecRestoreArray(gvec,NULL);CHKERRQ(ierr);
14120298fd71SBarry Smith   ierr = VecRestoreArray(lvec,NULL);CHKERRQ(ierr);
141347c6ae99SBarry Smith   PetscFunctionReturn(0);
141447c6ae99SBarry Smith }
141547c6ae99SBarry Smith 
141647c6ae99SBarry Smith #undef __FUNCT__
14170c010503SBarry Smith #define __FUNCT__ "DMGlobalToLocalEnd_Composite"
14187087cfbeSBarry Smith PetscErrorCode  DMGlobalToLocalEnd_Composite(DM dm,Vec gvec,InsertMode mode,Vec lvec)
14190c010503SBarry Smith {
14200c010503SBarry Smith   PetscFunctionBegin;
14210c010503SBarry Smith   PetscFunctionReturn(0);
14220c010503SBarry Smith }
142347c6ae99SBarry Smith 
14246ae3a549SBarry Smith /*MC
14256ae3a549SBarry Smith    DMCOMPOSITE = "composite" - A DM object that is used to manage data for a collection of DMs
14266ae3a549SBarry Smith 
14276ae3a549SBarry Smith   Level: intermediate
14286ae3a549SBarry Smith 
14291abcec8cSBarry Smith .seealso: DMType, DM, DMDACreate(), DMCreate(), DMSetType(), DMCompositeCreate()
14306ae3a549SBarry Smith M*/
14316ae3a549SBarry Smith 
14326ae3a549SBarry Smith 
1433a4121054SBarry Smith #undef __FUNCT__
1434a4121054SBarry Smith #define __FUNCT__ "DMCreate_Composite"
14358cc058d9SJed Brown PETSC_EXTERN PetscErrorCode DMCreate_Composite(DM p)
1436a4121054SBarry Smith {
1437a4121054SBarry Smith   PetscErrorCode ierr;
1438a4121054SBarry Smith   DM_Composite   *com;
1439a4121054SBarry Smith 
1440a4121054SBarry Smith   PetscFunctionBegin;
1441b00a9115SJed Brown   ierr      = PetscNewLog(p,&com);CHKERRQ(ierr);
1442a4121054SBarry Smith   p->data   = com;
1443a4121054SBarry Smith   ierr      = PetscObjectChangeTypeName((PetscObject)p,"DMComposite");CHKERRQ(ierr);
1444a4121054SBarry Smith   com->n    = 0;
14450298fd71SBarry Smith   com->next = NULL;
1446a4121054SBarry Smith   com->nDM  = 0;
1447a4121054SBarry Smith 
1448a4121054SBarry Smith   p->ops->createglobalvector              = DMCreateGlobalVector_Composite;
1449a4121054SBarry Smith   p->ops->createlocalvector               = DMCreateLocalVector_Composite;
1450184d77edSJed Brown   p->ops->getlocaltoglobalmapping         = DMGetLocalToGlobalMapping_Composite;
14514d343eeaSMatthew G Knepley   p->ops->createfieldis                   = DMCreateFieldIS_Composite;
145216621825SDmitry Karpeev   p->ops->createfielddecomposition        = DMCreateFieldDecomposition_Composite;
1453a4121054SBarry Smith   p->ops->refine                          = DMRefine_Composite;
145414354c39SJed Brown   p->ops->coarsen                         = DMCoarsen_Composite;
145525296bd5SBarry Smith   p->ops->createinterpolation             = DMCreateInterpolation_Composite;
145625296bd5SBarry Smith   p->ops->creatematrix                    = DMCreateMatrix_Composite;
1457e727c939SJed Brown   p->ops->getcoloring                     = DMCreateColoring_Composite;
1458a4121054SBarry Smith   p->ops->globaltolocalbegin              = DMGlobalToLocalBegin_Composite;
1459a4121054SBarry Smith   p->ops->globaltolocalend                = DMGlobalToLocalEnd_Composite;
1460a4121054SBarry Smith   p->ops->destroy                         = DMDestroy_Composite;
1461a4121054SBarry Smith   p->ops->view                            = DMView_Composite;
1462a4121054SBarry Smith   p->ops->setup                           = DMSetUp_Composite;
1463a4121054SBarry Smith   PetscFunctionReturn(0);
1464a4121054SBarry Smith }
1465a4121054SBarry Smith 
14660c010503SBarry Smith #undef __FUNCT__
14670c010503SBarry Smith #define __FUNCT__ "DMCompositeCreate"
14680c010503SBarry Smith /*@C
14690c010503SBarry Smith     DMCompositeCreate - Creates a vector packer, used to generate "composite"
14700c010503SBarry Smith       vectors made up of several subvectors.
14710c010503SBarry Smith 
14720c010503SBarry Smith     Collective on MPI_Comm
147347c6ae99SBarry Smith 
147447c6ae99SBarry Smith     Input Parameter:
14750c010503SBarry Smith .   comm - the processors that will share the global vector
14760c010503SBarry Smith 
14770c010503SBarry Smith     Output Parameters:
14780c010503SBarry Smith .   packer - the packer object
147947c6ae99SBarry Smith 
148047c6ae99SBarry Smith     Level: advanced
148147c6ae99SBarry Smith 
14821abcec8cSBarry Smith .seealso DMDestroy(), DMCompositeAddDM(), DMCompositeScatter(), DMCOMPOSITE,DMCreate()
14836eb61c8cSJed Brown          DMCompositeGather(), DMCreateGlobalVector(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess()
148447c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
148547c6ae99SBarry Smith 
148647c6ae99SBarry Smith @*/
14877087cfbeSBarry Smith PetscErrorCode  DMCompositeCreate(MPI_Comm comm,DM *packer)
148847c6ae99SBarry Smith {
14890c010503SBarry Smith   PetscErrorCode ierr;
14900c010503SBarry Smith 
149147c6ae99SBarry Smith   PetscFunctionBegin;
14920c010503SBarry Smith   PetscValidPointer(packer,2);
1493a4121054SBarry Smith   ierr = DMCreate(comm,packer);CHKERRQ(ierr);
1494a4121054SBarry Smith   ierr = DMSetType(*packer,DMCOMPOSITE);CHKERRQ(ierr);
149547c6ae99SBarry Smith   PetscFunctionReturn(0);
149647c6ae99SBarry Smith }
1497