xref: /petsc/src/dm/impls/composite/pack.c (revision 47c6ae997ffd1b2afd66b6474dff5950ae8613d1)
1*47c6ae99SBarry Smith #define PETSCDM_DLL
2*47c6ae99SBarry Smith 
3*47c6ae99SBarry Smith #include "petscda.h"             /*I      "petscda.h"     I*/
4*47c6ae99SBarry Smith #include "private/dmimpl.h"
5*47c6ae99SBarry Smith #include "petscmat.h"
6*47c6ae99SBarry Smith 
7*47c6ae99SBarry Smith /*
8*47c6ae99SBarry Smith    rstart is where an array/subvector starts in the global parallel vector, so arrays
9*47c6ae99SBarry Smith    rstarts are meaningless (and set to the previous one) except on the processor where the array lives
10*47c6ae99SBarry Smith */
11*47c6ae99SBarry Smith 
12*47c6ae99SBarry Smith typedef enum {DMCOMPOSITE_ARRAY, DMCOMPOSITE_DM} DMCompositeLinkType;
13*47c6ae99SBarry Smith 
14*47c6ae99SBarry Smith struct DMCompositeLink {
15*47c6ae99SBarry Smith   DMCompositeLinkType    type;
16*47c6ae99SBarry Smith   struct DMCompositeLink *next;
17*47c6ae99SBarry Smith   PetscInt               n,rstart;      /* rstart is relative to this process */
18*47c6ae99SBarry Smith   PetscInt               grstart;       /* grstart is relative to all processes */
19*47c6ae99SBarry Smith 
20*47c6ae99SBarry Smith   /* only used for DMCOMPOSITE_DM */
21*47c6ae99SBarry Smith   PetscInt               *grstarts;     /* global row for first unknown of this DM on each process */
22*47c6ae99SBarry Smith   DM                     dm;
23*47c6ae99SBarry Smith 
24*47c6ae99SBarry Smith   /* only used for DMCOMPOSITE_ARRAY */
25*47c6ae99SBarry Smith   PetscMPIInt            rank;          /* process where array unknowns live */
26*47c6ae99SBarry Smith };
27*47c6ae99SBarry Smith 
28*47c6ae99SBarry Smith typedef struct {
29*47c6ae99SBarry Smith   PetscInt               n,N,rstart;           /* rstart is relative to all processors, n unknowns owned by this process, N is total unknowns */
30*47c6ae99SBarry Smith   PetscInt               nghost;               /* number of all local entries include DA ghost points and any shared redundant arrays */
31*47c6ae99SBarry Smith   PetscInt               nDM,nredundant,nmine; /* how many DM's and seperate redundant arrays used to build DM(nmine is ones on this process) */
32*47c6ae99SBarry Smith   PetscBool              setup;                /* after this is set, cannot add new links to the DM*/
33*47c6ae99SBarry Smith   struct DMCompositeLink *next;
34*47c6ae99SBarry Smith 
35*47c6ae99SBarry Smith   PetscErrorCode (*FormCoupleLocations)(DM,Mat,PetscInt*,PetscInt*,PetscInt,PetscInt,PetscInt,PetscInt);
36*47c6ae99SBarry Smith } DM_Composite;
37*47c6ae99SBarry Smith 
38*47c6ae99SBarry Smith #undef __FUNCT__
39*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeSetCoupling"
40*47c6ae99SBarry Smith /*@C
41*47c6ae99SBarry Smith     DMCompositeSetCoupling - Sets user provided routines that compute the coupling between the
42*47c6ae99SBarry Smith       seperate components (DA's and arrays) in a DMto build the correct matrix nonzero structure.
43*47c6ae99SBarry Smith 
44*47c6ae99SBarry Smith 
45*47c6ae99SBarry Smith     Logically Collective on MPI_Comm
46*47c6ae99SBarry Smith 
47*47c6ae99SBarry Smith     Input Parameter:
48*47c6ae99SBarry Smith +   dm - the composite object
49*47c6ae99SBarry Smith -   formcouplelocations - routine to set the nonzero locations in the matrix
50*47c6ae99SBarry Smith 
51*47c6ae99SBarry Smith     Level: advanced
52*47c6ae99SBarry Smith 
53*47c6ae99SBarry Smith     Notes: See DMCompositeSetContext() and DMCompositeGetContext() for how to get user information into
54*47c6ae99SBarry Smith         this routine
55*47c6ae99SBarry Smith 
56*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeScatter(),
57*47c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreateGlobalVector(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess()
58*47c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries(), DMCompositeSetContext(),
59*47c6ae99SBarry Smith          DMCompositeGetContext()
60*47c6ae99SBarry Smith 
61*47c6ae99SBarry Smith @*/
62*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeSetCoupling(DM dm,PetscErrorCode (*FormCoupleLocations)(DM,Mat,PetscInt*,PetscInt*,PetscInt,PetscInt,PetscInt,PetscInt))
63*47c6ae99SBarry Smith {
64*47c6ae99SBarry Smith   DM_Composite *com = (DM_Composite*)dm->data;
65*47c6ae99SBarry Smith 
66*47c6ae99SBarry Smith   PetscFunctionBegin;
67*47c6ae99SBarry Smith   com->FormCoupleLocations = FormCoupleLocations;
68*47c6ae99SBarry Smith   PetscFunctionReturn(0);
69*47c6ae99SBarry Smith }
70*47c6ae99SBarry Smith 
71*47c6ae99SBarry Smith #undef __FUNCT__
72*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeSetContext"
73*47c6ae99SBarry Smith /*@
74*47c6ae99SBarry Smith     DMCompositeSetContext - Allows user to stash data they may need within the form coupling routine they
75*47c6ae99SBarry Smith       set with DMCompositeSetCoupling()
76*47c6ae99SBarry Smith 
77*47c6ae99SBarry Smith 
78*47c6ae99SBarry Smith     Not Collective
79*47c6ae99SBarry Smith 
80*47c6ae99SBarry Smith     Input Parameter:
81*47c6ae99SBarry Smith +   dm - the composite object
82*47c6ae99SBarry Smith -   ctx - the user supplied context
83*47c6ae99SBarry Smith 
84*47c6ae99SBarry Smith     Level: advanced
85*47c6ae99SBarry Smith 
86*47c6ae99SBarry Smith     Notes: Use DMCompositeGetContext() to retrieve the context when needed.
87*47c6ae99SBarry Smith 
88*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeScatter(),
89*47c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreateGlobalVector(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess()
90*47c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries(), DMCompositeSetCoupling(),
91*47c6ae99SBarry Smith          DMCompositeGetContext()
92*47c6ae99SBarry Smith 
93*47c6ae99SBarry Smith @*/
94*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeSetContext(DM dm,void *ctx)
95*47c6ae99SBarry Smith {
96*47c6ae99SBarry Smith   PetscFunctionBegin;
97*47c6ae99SBarry Smith   dm->ctx = ctx;
98*47c6ae99SBarry Smith   PetscFunctionReturn(0);
99*47c6ae99SBarry Smith }
100*47c6ae99SBarry Smith 
101*47c6ae99SBarry Smith #undef __FUNCT__
102*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetContext"
103*47c6ae99SBarry Smith /*@
104*47c6ae99SBarry Smith     DMCompositeGetContext - Access the context set with DMCompositeSetContext()
105*47c6ae99SBarry Smith 
106*47c6ae99SBarry Smith 
107*47c6ae99SBarry Smith     Not Collective
108*47c6ae99SBarry Smith 
109*47c6ae99SBarry Smith     Input Parameter:
110*47c6ae99SBarry Smith .   dm - the composite object
111*47c6ae99SBarry Smith 
112*47c6ae99SBarry Smith     Output Parameter:
113*47c6ae99SBarry Smith .    ctx - the user supplied context
114*47c6ae99SBarry Smith 
115*47c6ae99SBarry Smith     Level: advanced
116*47c6ae99SBarry Smith 
117*47c6ae99SBarry Smith     Notes: Use DMCompositeGetContext() to retrieve the context when needed.
118*47c6ae99SBarry Smith 
119*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeScatter(),
120*47c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreateGlobalVector(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess()
121*47c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries(), DMCompositeSetCoupling(),
122*47c6ae99SBarry Smith          DMCompositeSetContext()
123*47c6ae99SBarry Smith 
124*47c6ae99SBarry Smith @*/
125*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGetContext(DM dm,void **ctx)
126*47c6ae99SBarry Smith {
127*47c6ae99SBarry Smith   PetscFunctionBegin;
128*47c6ae99SBarry Smith   *ctx = dm->ctx;
129*47c6ae99SBarry Smith   PetscFunctionReturn(0);
130*47c6ae99SBarry Smith }
131*47c6ae99SBarry Smith 
132*47c6ae99SBarry Smith 
133*47c6ae99SBarry Smith #undef __FUNCT__
134*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeCreate"
135*47c6ae99SBarry Smith /*@C
136*47c6ae99SBarry Smith     DMCompositeCreate - Creates a vector packer, used to generate "composite"
137*47c6ae99SBarry Smith       vectors made up of several subvectors.
138*47c6ae99SBarry Smith 
139*47c6ae99SBarry Smith     Collective on MPI_Comm
140*47c6ae99SBarry Smith 
141*47c6ae99SBarry Smith     Input Parameter:
142*47c6ae99SBarry Smith .   comm - the processors that will share the global vector
143*47c6ae99SBarry Smith 
144*47c6ae99SBarry Smith     Output Parameters:
145*47c6ae99SBarry Smith .   packer - the packer object
146*47c6ae99SBarry Smith 
147*47c6ae99SBarry Smith     Level: advanced
148*47c6ae99SBarry Smith 
149*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeScatter(),
150*47c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreateGlobalVector(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess()
151*47c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
152*47c6ae99SBarry Smith 
153*47c6ae99SBarry Smith @*/
154*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeCreate(MPI_Comm comm,DM *packer)
155*47c6ae99SBarry Smith {
156*47c6ae99SBarry Smith   PetscErrorCode ierr;
157*47c6ae99SBarry Smith   DM             p;
158*47c6ae99SBarry Smith   DM_Composite   *com;
159*47c6ae99SBarry Smith 
160*47c6ae99SBarry Smith   PetscFunctionBegin;
161*47c6ae99SBarry Smith   PetscValidPointer(packer,2);
162*47c6ae99SBarry Smith   *packer = PETSC_NULL;
163*47c6ae99SBarry Smith #ifndef PETSC_USE_DYNAMIC_LIBRARIES
164*47c6ae99SBarry Smith   ierr = DMInitializePackage(PETSC_NULL);CHKERRQ(ierr);
165*47c6ae99SBarry Smith #endif
166*47c6ae99SBarry Smith 
167*47c6ae99SBarry Smith   ierr = PetscHeaderCreate(p,_p_DM,struct _DMOps,DM_CLASSID,0,"DM",comm,DMCompositeDestroy,DMCompositeView);CHKERRQ(ierr);
168*47c6ae99SBarry Smith   ierr = PetscNewLog(p,DM_Composite,&com);CHKERRQ(ierr);
169*47c6ae99SBarry Smith   p->data = com;
170*47c6ae99SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)p,"DMComposite");CHKERRQ(ierr);
171*47c6ae99SBarry Smith   com->n            = 0;
172*47c6ae99SBarry Smith   com->next         = PETSC_NULL;
173*47c6ae99SBarry Smith   com->nredundant   = 0;
174*47c6ae99SBarry Smith   com->nDM          = 0;
175*47c6ae99SBarry Smith 
176*47c6ae99SBarry Smith   p->ops->createglobalvector = DMCompositeCreateGlobalVector;
177*47c6ae99SBarry Smith   p->ops->createlocalvector  = DMCompositeCreateLocalVector;
178*47c6ae99SBarry Smith   p->ops->refine             = DMCompositeRefine;
179*47c6ae99SBarry Smith   p->ops->getinterpolation   = DMCompositeGetInterpolation;
180*47c6ae99SBarry Smith   p->ops->getmatrix          = DMCompositeGetMatrix;
181*47c6ae99SBarry Smith   p->ops->getcoloring        = DMCompositeGetColoring;
182*47c6ae99SBarry Smith   p->ops->globaltolocalbegin = DMCompositeGlobalToLocalBegin;
183*47c6ae99SBarry Smith   p->ops->globaltolocalend   = DMCompositeGlobalToLocalEnd;
184*47c6ae99SBarry Smith   p->ops->destroy            = DMCompositeDestroy;
185*47c6ae99SBarry Smith 
186*47c6ae99SBarry Smith   *packer = p;
187*47c6ae99SBarry Smith   PetscFunctionReturn(0);
188*47c6ae99SBarry Smith }
189*47c6ae99SBarry Smith 
190*47c6ae99SBarry Smith extern PetscErrorCode DMDestroy_Private(DM,PetscBool *);
191*47c6ae99SBarry Smith 
192*47c6ae99SBarry Smith #undef __FUNCT__
193*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeDestroy"
194*47c6ae99SBarry Smith /*@C
195*47c6ae99SBarry Smith     DMCompositeDestroy - Destroys a vector packer.
196*47c6ae99SBarry Smith 
197*47c6ae99SBarry Smith     Collective on DMComposite
198*47c6ae99SBarry Smith 
199*47c6ae99SBarry Smith     Input Parameter:
200*47c6ae99SBarry Smith .   packer - the packer object
201*47c6ae99SBarry Smith 
202*47c6ae99SBarry Smith     Level: advanced
203*47c6ae99SBarry Smith 
204*47c6ae99SBarry Smith .seealso DMCompositeCreate(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeScatter(),DMCompositeGetEntries()
205*47c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreateGlobalVector(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess()
206*47c6ae99SBarry Smith 
207*47c6ae99SBarry Smith @*/
208*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeDestroy(DM dm)
209*47c6ae99SBarry Smith {
210*47c6ae99SBarry Smith   PetscErrorCode         ierr;
211*47c6ae99SBarry Smith   struct DMCompositeLink *next, *prev;
212*47c6ae99SBarry Smith   PetscBool              done;
213*47c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite *)dm->data;
214*47c6ae99SBarry Smith 
215*47c6ae99SBarry Smith   PetscFunctionBegin;
216*47c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
217*47c6ae99SBarry Smith   ierr = DMDestroy_Private((DM)dm,&done);CHKERRQ(ierr);
218*47c6ae99SBarry Smith   if (!done) PetscFunctionReturn(0);
219*47c6ae99SBarry Smith 
220*47c6ae99SBarry Smith   next = com->next;
221*47c6ae99SBarry Smith   while (next) {
222*47c6ae99SBarry Smith     prev = next;
223*47c6ae99SBarry Smith     next = next->next;
224*47c6ae99SBarry Smith     if (prev->type == DMCOMPOSITE_DM) {
225*47c6ae99SBarry Smith       ierr = DMDestroy(prev->dm);CHKERRQ(ierr);
226*47c6ae99SBarry Smith     }
227*47c6ae99SBarry Smith     if (prev->grstarts) {
228*47c6ae99SBarry Smith       ierr = PetscFree(prev->grstarts);CHKERRQ(ierr);
229*47c6ae99SBarry Smith     }
230*47c6ae99SBarry Smith     ierr = PetscFree(prev);CHKERRQ(ierr);
231*47c6ae99SBarry Smith   }
232*47c6ae99SBarry Smith   ierr = PetscFree(com);CHKERRQ(ierr);
233*47c6ae99SBarry Smith   ierr = PetscHeaderDestroy(dm);CHKERRQ(ierr);
234*47c6ae99SBarry Smith   PetscFunctionReturn(0);
235*47c6ae99SBarry Smith }
236*47c6ae99SBarry Smith 
237*47c6ae99SBarry Smith #undef __FUNCT__
238*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeView"
239*47c6ae99SBarry Smith /*@
240*47c6ae99SBarry Smith     DMCompositeView - Views a composite DM
241*47c6ae99SBarry Smith 
242*47c6ae99SBarry Smith     Collective on DMComposite
243*47c6ae99SBarry Smith 
244*47c6ae99SBarry Smith     Input Parameter:
245*47c6ae99SBarry Smith +   packer - the DMobject to view
246*47c6ae99SBarry Smith -   v - the viewer
247*47c6ae99SBarry Smith 
248*47c6ae99SBarry Smith     Level: intermediate
249*47c6ae99SBarry Smith 
250*47c6ae99SBarry Smith .seealso DMCompositeCreate()
251*47c6ae99SBarry Smith 
252*47c6ae99SBarry Smith @*/
253*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeView(DM dm,PetscViewer v)
254*47c6ae99SBarry Smith {
255*47c6ae99SBarry Smith   PetscErrorCode ierr;
256*47c6ae99SBarry Smith   PetscBool      iascii;
257*47c6ae99SBarry Smith   DM_Composite   *com = (DM_Composite *)dm->data;
258*47c6ae99SBarry Smith 
259*47c6ae99SBarry Smith   PetscFunctionBegin;
260*47c6ae99SBarry Smith   ierr = PetscTypeCompare((PetscObject)v,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
261*47c6ae99SBarry Smith   if (iascii) {
262*47c6ae99SBarry Smith     struct DMCompositeLink *lnk = com->next;
263*47c6ae99SBarry Smith     PetscInt               i;
264*47c6ae99SBarry Smith 
265*47c6ae99SBarry Smith     ierr = PetscViewerASCIIPrintf(v,"DM (%s)\n",((PetscObject)dm)->prefix?((PetscObject)dm)->prefix:"no prefix");CHKERRQ(ierr);
266*47c6ae99SBarry Smith     ierr = PetscViewerASCIIPrintf(v,"  contains %d DMs and %d redundant arrays\n",com->nDM,com->nredundant);CHKERRQ(ierr);
267*47c6ae99SBarry Smith     ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr);
268*47c6ae99SBarry Smith     for (i=0; lnk; lnk=lnk->next,i++) {
269*47c6ae99SBarry Smith       if (lnk->dm) {
270*47c6ae99SBarry Smith         ierr = PetscViewerASCIIPrintf(v,"Link %d: DM of type %s\n",i,((PetscObject)lnk->dm)->type_name);CHKERRQ(ierr);
271*47c6ae99SBarry Smith         ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr);
272*47c6ae99SBarry Smith         ierr = DMView(lnk->dm,v);CHKERRQ(ierr);
273*47c6ae99SBarry Smith         ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr);
274*47c6ae99SBarry Smith       } else {
275*47c6ae99SBarry Smith         ierr = PetscViewerASCIIPrintf(v,"Link %d: Redundant array of size %d owned by rank %d\n",i,lnk->n,lnk->rank);CHKERRQ(ierr);
276*47c6ae99SBarry Smith       }
277*47c6ae99SBarry Smith     }
278*47c6ae99SBarry Smith     ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr);
279*47c6ae99SBarry Smith   }
280*47c6ae99SBarry Smith   PetscFunctionReturn(0);
281*47c6ae99SBarry Smith }
282*47c6ae99SBarry Smith 
283*47c6ae99SBarry Smith /* --------------------------------------------------------------------------------------*/
284*47c6ae99SBarry Smith #undef __FUNCT__
285*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeSetUp"
286*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeSetUp(DM dm)
287*47c6ae99SBarry Smith {
288*47c6ae99SBarry Smith   PetscErrorCode         ierr;
289*47c6ae99SBarry Smith   PetscInt               nprev = 0;
290*47c6ae99SBarry Smith   PetscMPIInt            rank,size;
291*47c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
292*47c6ae99SBarry Smith   struct DMCompositeLink *next = com->next;
293*47c6ae99SBarry Smith   PetscLayout            map;
294*47c6ae99SBarry Smith 
295*47c6ae99SBarry Smith   PetscFunctionBegin;
296*47c6ae99SBarry Smith   if (com->setup) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"Packer has already been setup");
297*47c6ae99SBarry Smith   ierr = PetscLayoutCreate(((PetscObject)dm)->comm,&map);CHKERRQ(ierr);
298*47c6ae99SBarry Smith   ierr = PetscLayoutSetLocalSize(map,com->n);CHKERRQ(ierr);
299*47c6ae99SBarry Smith   ierr = PetscLayoutSetSize(map,PETSC_DETERMINE);CHKERRQ(ierr);
300*47c6ae99SBarry Smith   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
301*47c6ae99SBarry Smith   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
302*47c6ae99SBarry Smith   ierr = PetscLayoutGetSize(map,&com->N);CHKERRQ(ierr);
303*47c6ae99SBarry Smith   ierr = PetscLayoutGetRange(map,&com->rstart,PETSC_NULL);CHKERRQ(ierr);
304*47c6ae99SBarry Smith   ierr = PetscLayoutDestroy(map);CHKERRQ(ierr);
305*47c6ae99SBarry Smith 
306*47c6ae99SBarry Smith   /* now set the rstart for each linked array/vector */
307*47c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
308*47c6ae99SBarry Smith   ierr = MPI_Comm_size(((PetscObject)dm)->comm,&size);CHKERRQ(ierr);
309*47c6ae99SBarry Smith   while (next) {
310*47c6ae99SBarry Smith     next->rstart = nprev;
311*47c6ae99SBarry Smith     if ((rank == next->rank) || next->type != DMCOMPOSITE_ARRAY) nprev += next->n;
312*47c6ae99SBarry Smith     next->grstart = com->rstart + next->rstart;
313*47c6ae99SBarry Smith     if (next->type == DMCOMPOSITE_ARRAY) {
314*47c6ae99SBarry Smith       ierr = MPI_Bcast(&next->grstart,1,MPIU_INT,next->rank,((PetscObject)dm)->comm);CHKERRQ(ierr);
315*47c6ae99SBarry Smith     } else {
316*47c6ae99SBarry Smith       ierr = PetscMalloc(size*sizeof(PetscInt),&next->grstarts);CHKERRQ(ierr);
317*47c6ae99SBarry Smith       ierr = MPI_Allgather(&next->grstart,1,MPIU_INT,next->grstarts,1,MPIU_INT,((PetscObject)dm)->comm);CHKERRQ(ierr);
318*47c6ae99SBarry Smith     }
319*47c6ae99SBarry Smith     next = next->next;
320*47c6ae99SBarry Smith   }
321*47c6ae99SBarry Smith   com->setup = PETSC_TRUE;
322*47c6ae99SBarry Smith   PetscFunctionReturn(0);
323*47c6ae99SBarry Smith }
324*47c6ae99SBarry Smith 
325*47c6ae99SBarry Smith 
326*47c6ae99SBarry Smith #undef __FUNCT__
327*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetAccess_Array"
328*47c6ae99SBarry Smith PetscErrorCode DMCompositeGetAccess_Array(DM dm,struct DMCompositeLink *mine,Vec vec,PetscScalar **array)
329*47c6ae99SBarry Smith {
330*47c6ae99SBarry Smith   PetscErrorCode ierr;
331*47c6ae99SBarry Smith   PetscScalar    *varray;
332*47c6ae99SBarry Smith   PetscMPIInt    rank;
333*47c6ae99SBarry Smith 
334*47c6ae99SBarry Smith   PetscFunctionBegin;
335*47c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
336*47c6ae99SBarry Smith   if (array) {
337*47c6ae99SBarry Smith     if (rank == mine->rank) {
338*47c6ae99SBarry Smith       ierr    = VecGetArray(vec,&varray);CHKERRQ(ierr);
339*47c6ae99SBarry Smith       *array  = varray + mine->rstart;
340*47c6ae99SBarry Smith       ierr    = VecRestoreArray(vec,&varray);CHKERRQ(ierr);
341*47c6ae99SBarry Smith     } else {
342*47c6ae99SBarry Smith       *array = 0;
343*47c6ae99SBarry Smith     }
344*47c6ae99SBarry Smith   }
345*47c6ae99SBarry Smith   PetscFunctionReturn(0);
346*47c6ae99SBarry Smith }
347*47c6ae99SBarry Smith 
348*47c6ae99SBarry Smith #undef __FUNCT__
349*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetAccess_DM"
350*47c6ae99SBarry Smith PetscErrorCode DMCompositeGetAccess_DM(DM dm,struct DMCompositeLink *mine,Vec vec,Vec *global)
351*47c6ae99SBarry Smith {
352*47c6ae99SBarry Smith   PetscErrorCode ierr;
353*47c6ae99SBarry Smith   PetscScalar    *array;
354*47c6ae99SBarry Smith 
355*47c6ae99SBarry Smith   PetscFunctionBegin;
356*47c6ae99SBarry Smith   if (global) {
357*47c6ae99SBarry Smith     ierr    = DMGetGlobalVector(mine->dm,global);CHKERRQ(ierr);
358*47c6ae99SBarry Smith     ierr    = VecGetArray(vec,&array);CHKERRQ(ierr);
359*47c6ae99SBarry Smith     ierr    = VecPlaceArray(*global,array+mine->rstart);CHKERRQ(ierr);
360*47c6ae99SBarry Smith     ierr    = VecRestoreArray(vec,&array);CHKERRQ(ierr);
361*47c6ae99SBarry Smith   }
362*47c6ae99SBarry Smith   PetscFunctionReturn(0);
363*47c6ae99SBarry Smith }
364*47c6ae99SBarry Smith 
365*47c6ae99SBarry Smith #undef __FUNCT__
366*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeRestoreAccess_Array"
367*47c6ae99SBarry Smith PetscErrorCode DMCompositeRestoreAccess_Array(DM dm,struct DMCompositeLink *mine,Vec vec,PetscScalar **array)
368*47c6ae99SBarry Smith {
369*47c6ae99SBarry Smith   PetscFunctionBegin;
370*47c6ae99SBarry Smith   PetscFunctionReturn(0);
371*47c6ae99SBarry Smith }
372*47c6ae99SBarry Smith 
373*47c6ae99SBarry Smith #undef __FUNCT__
374*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeRestoreAccess_DM"
375*47c6ae99SBarry Smith PetscErrorCode DMCompositeRestoreAccess_DM(DM dm,struct DMCompositeLink *mine,Vec vec,Vec *global)
376*47c6ae99SBarry Smith {
377*47c6ae99SBarry Smith   PetscErrorCode ierr;
378*47c6ae99SBarry Smith 
379*47c6ae99SBarry Smith   PetscFunctionBegin;
380*47c6ae99SBarry Smith   if (global) {
381*47c6ae99SBarry Smith     ierr = VecResetArray(*global);CHKERRQ(ierr);
382*47c6ae99SBarry Smith     ierr = DMRestoreGlobalVector(mine->dm,global);CHKERRQ(ierr);
383*47c6ae99SBarry Smith   }
384*47c6ae99SBarry Smith   PetscFunctionReturn(0);
385*47c6ae99SBarry Smith }
386*47c6ae99SBarry Smith 
387*47c6ae99SBarry Smith #undef __FUNCT__
388*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeScatter_Array"
389*47c6ae99SBarry Smith PetscErrorCode DMCompositeScatter_Array(DM dm,struct DMCompositeLink *mine,Vec vec,PetscScalar *array)
390*47c6ae99SBarry Smith {
391*47c6ae99SBarry Smith   PetscErrorCode ierr;
392*47c6ae99SBarry Smith   PetscScalar    *varray;
393*47c6ae99SBarry Smith   PetscMPIInt    rank;
394*47c6ae99SBarry Smith 
395*47c6ae99SBarry Smith   PetscFunctionBegin;
396*47c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
397*47c6ae99SBarry Smith   if (rank == mine->rank) {
398*47c6ae99SBarry Smith     ierr    = VecGetArray(vec,&varray);CHKERRQ(ierr);
399*47c6ae99SBarry Smith     ierr    = PetscMemcpy(array,varray+mine->rstart,mine->n*sizeof(PetscScalar));CHKERRQ(ierr);
400*47c6ae99SBarry Smith     ierr    = VecRestoreArray(vec,&varray);CHKERRQ(ierr);
401*47c6ae99SBarry Smith   }
402*47c6ae99SBarry Smith   ierr    = MPI_Bcast(array,mine->n,MPIU_SCALAR,mine->rank,((PetscObject)dm)->comm);CHKERRQ(ierr);
403*47c6ae99SBarry Smith   PetscFunctionReturn(0);
404*47c6ae99SBarry Smith }
405*47c6ae99SBarry Smith 
406*47c6ae99SBarry Smith #undef __FUNCT__
407*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeScatter_DM"
408*47c6ae99SBarry Smith PetscErrorCode DMCompositeScatter_DM(DM dm,struct DMCompositeLink *mine,Vec vec,Vec local)
409*47c6ae99SBarry Smith {
410*47c6ae99SBarry Smith   PetscErrorCode ierr;
411*47c6ae99SBarry Smith   PetscScalar    *array;
412*47c6ae99SBarry Smith   Vec            global;
413*47c6ae99SBarry Smith 
414*47c6ae99SBarry Smith   PetscFunctionBegin;
415*47c6ae99SBarry Smith   ierr = DMGetGlobalVector(mine->dm,&global);CHKERRQ(ierr);
416*47c6ae99SBarry Smith   ierr = VecGetArray(vec,&array);CHKERRQ(ierr);
417*47c6ae99SBarry Smith   ierr = VecPlaceArray(global,array+mine->rstart);CHKERRQ(ierr);
418*47c6ae99SBarry Smith   ierr = DMGlobalToLocalBegin(mine->dm,global,INSERT_VALUES,local);CHKERRQ(ierr);
419*47c6ae99SBarry Smith   ierr = DMGlobalToLocalEnd(mine->dm,global,INSERT_VALUES,local);CHKERRQ(ierr);
420*47c6ae99SBarry Smith   ierr = VecRestoreArray(vec,&array);CHKERRQ(ierr);
421*47c6ae99SBarry Smith   ierr = VecResetArray(global);CHKERRQ(ierr);
422*47c6ae99SBarry Smith   ierr = DMRestoreGlobalVector(mine->dm,&global);CHKERRQ(ierr);
423*47c6ae99SBarry Smith   PetscFunctionReturn(0);
424*47c6ae99SBarry Smith }
425*47c6ae99SBarry Smith 
426*47c6ae99SBarry Smith #undef __FUNCT__
427*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGather_Array"
428*47c6ae99SBarry Smith PetscErrorCode DMCompositeGather_Array(DM dm,struct DMCompositeLink *mine,Vec vec,PetscScalar *array)
429*47c6ae99SBarry Smith {
430*47c6ae99SBarry Smith   PetscErrorCode ierr;
431*47c6ae99SBarry Smith   PetscScalar    *varray;
432*47c6ae99SBarry Smith   PetscMPIInt    rank;
433*47c6ae99SBarry Smith 
434*47c6ae99SBarry Smith   PetscFunctionBegin;
435*47c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
436*47c6ae99SBarry Smith   if (rank == mine->rank) {
437*47c6ae99SBarry Smith     ierr    = VecGetArray(vec,&varray);CHKERRQ(ierr);
438*47c6ae99SBarry Smith     if (varray+mine->rstart == array) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"You need not DMCompositeGather() into objects obtained via DMCompositeGetAccess()");
439*47c6ae99SBarry Smith     ierr    = PetscMemcpy(varray+mine->rstart,array,mine->n*sizeof(PetscScalar));CHKERRQ(ierr);
440*47c6ae99SBarry Smith     ierr    = VecRestoreArray(vec,&varray);CHKERRQ(ierr);
441*47c6ae99SBarry Smith   }
442*47c6ae99SBarry Smith   PetscFunctionReturn(0);
443*47c6ae99SBarry Smith }
444*47c6ae99SBarry Smith 
445*47c6ae99SBarry Smith #undef __FUNCT__
446*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGather_DM"
447*47c6ae99SBarry Smith PetscErrorCode DMCompositeGather_DM(DM dm,struct DMCompositeLink *mine,Vec vec,Vec local)
448*47c6ae99SBarry Smith {
449*47c6ae99SBarry Smith   PetscErrorCode ierr;
450*47c6ae99SBarry Smith   PetscScalar    *array;
451*47c6ae99SBarry Smith   Vec            global;
452*47c6ae99SBarry Smith 
453*47c6ae99SBarry Smith   PetscFunctionBegin;
454*47c6ae99SBarry Smith   ierr = DMGetGlobalVector(mine->dm,&global);CHKERRQ(ierr);
455*47c6ae99SBarry Smith   ierr = VecGetArray(vec,&array);CHKERRQ(ierr);
456*47c6ae99SBarry Smith   ierr = VecPlaceArray(global,array+mine->rstart);CHKERRQ(ierr);
457*47c6ae99SBarry Smith   ierr = DMLocalToGlobal(mine->dm,local,INSERT_VALUES,global);CHKERRQ(ierr);
458*47c6ae99SBarry Smith   ierr = VecRestoreArray(vec,&array);CHKERRQ(ierr);
459*47c6ae99SBarry Smith   ierr = VecResetArray(global);CHKERRQ(ierr);
460*47c6ae99SBarry Smith   ierr = DMRestoreGlobalVector(mine->dm,&global);CHKERRQ(ierr);
461*47c6ae99SBarry Smith   PetscFunctionReturn(0);
462*47c6ae99SBarry Smith }
463*47c6ae99SBarry Smith 
464*47c6ae99SBarry Smith /* ----------------------------------------------------------------------------------*/
465*47c6ae99SBarry Smith 
466*47c6ae99SBarry Smith #include <stdarg.h>
467*47c6ae99SBarry Smith 
468*47c6ae99SBarry Smith #undef __FUNCT__
469*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetNumberDM"
470*47c6ae99SBarry Smith /*@C
471*47c6ae99SBarry Smith     DMCompositeGetNumberDM - Get's the number of DM objects in the DMComposite
472*47c6ae99SBarry Smith        representation.
473*47c6ae99SBarry Smith 
474*47c6ae99SBarry Smith     Not Collective
475*47c6ae99SBarry Smith 
476*47c6ae99SBarry Smith     Input Parameter:
477*47c6ae99SBarry Smith .    dm - the packer object
478*47c6ae99SBarry Smith 
479*47c6ae99SBarry Smith     Output Parameter:
480*47c6ae99SBarry Smith .     nDM - the number of DMs
481*47c6ae99SBarry Smith 
482*47c6ae99SBarry Smith     Level: beginner
483*47c6ae99SBarry Smith 
484*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(),
485*47c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeScatter(),
486*47c6ae99SBarry Smith          DMCompositeRestoreAccess(), DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(),
487*47c6ae99SBarry Smith          DMCompositeGetEntries()
488*47c6ae99SBarry Smith 
489*47c6ae99SBarry Smith @*/
490*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGetNumberDM(DM dm,PetscInt *nDM)
491*47c6ae99SBarry Smith {
492*47c6ae99SBarry Smith   DM_Composite *com = (DM_Composite*)dm->data;
493*47c6ae99SBarry Smith   PetscFunctionBegin;
494*47c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
495*47c6ae99SBarry Smith   *nDM = com->nDM;
496*47c6ae99SBarry Smith   PetscFunctionReturn(0);
497*47c6ae99SBarry Smith }
498*47c6ae99SBarry Smith 
499*47c6ae99SBarry Smith 
500*47c6ae99SBarry Smith #undef __FUNCT__
501*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetAccess"
502*47c6ae99SBarry Smith /*@C
503*47c6ae99SBarry Smith     DMCompositeGetAccess - Allows one to access the individual packed vectors in their global
504*47c6ae99SBarry Smith        representation.
505*47c6ae99SBarry Smith 
506*47c6ae99SBarry Smith     Collective on DMComposite
507*47c6ae99SBarry Smith 
508*47c6ae99SBarry Smith     Input Parameter:
509*47c6ae99SBarry Smith +    dm - the packer object
510*47c6ae99SBarry Smith .    gvec - the global vector
511*47c6ae99SBarry Smith -    ... - the individual sequential or parallel objects (arrays or vectors)
512*47c6ae99SBarry Smith 
513*47c6ae99SBarry Smith     Notes: Use DMCompositeRestoreAccess() to return the vectors when you no longer need them
514*47c6ae99SBarry Smith 
515*47c6ae99SBarry Smith     Level: advanced
516*47c6ae99SBarry Smith 
517*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(),
518*47c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeScatter(),
519*47c6ae99SBarry Smith          DMCompositeRestoreAccess(), DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(),
520*47c6ae99SBarry Smith          DMCompositeGetEntries()
521*47c6ae99SBarry Smith 
522*47c6ae99SBarry Smith @*/
523*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGetAccess(DM dm,Vec gvec,...)
524*47c6ae99SBarry Smith {
525*47c6ae99SBarry Smith   va_list                Argp;
526*47c6ae99SBarry Smith   PetscErrorCode         ierr;
527*47c6ae99SBarry Smith   struct DMCompositeLink *next;
528*47c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
529*47c6ae99SBarry Smith 
530*47c6ae99SBarry Smith   PetscFunctionBegin;
531*47c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
532*47c6ae99SBarry Smith   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
533*47c6ae99SBarry Smith   next = com->next;
534*47c6ae99SBarry Smith   if (!com->setup) {
535*47c6ae99SBarry Smith     ierr = DMCompositeSetUp(dm);CHKERRQ(ierr);
536*47c6ae99SBarry Smith   }
537*47c6ae99SBarry Smith 
538*47c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
539*47c6ae99SBarry Smith   va_start(Argp,gvec);
540*47c6ae99SBarry Smith   while (next) {
541*47c6ae99SBarry Smith     if (next->type == DMCOMPOSITE_ARRAY) {
542*47c6ae99SBarry Smith       PetscScalar **array;
543*47c6ae99SBarry Smith       array = va_arg(Argp, PetscScalar**);
544*47c6ae99SBarry Smith       ierr  = DMCompositeGetAccess_Array(dm,next,gvec,array);CHKERRQ(ierr);
545*47c6ae99SBarry Smith     } else if (next->type == DMCOMPOSITE_DM) {
546*47c6ae99SBarry Smith       Vec *vec;
547*47c6ae99SBarry Smith       vec  = va_arg(Argp, Vec*);
548*47c6ae99SBarry Smith       ierr = DMCompositeGetAccess_DM(dm,next,gvec,vec);CHKERRQ(ierr);
549*47c6ae99SBarry Smith     } else {
550*47c6ae99SBarry Smith       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
551*47c6ae99SBarry Smith     }
552*47c6ae99SBarry Smith     next = next->next;
553*47c6ae99SBarry Smith   }
554*47c6ae99SBarry Smith   va_end(Argp);
555*47c6ae99SBarry Smith   PetscFunctionReturn(0);
556*47c6ae99SBarry Smith }
557*47c6ae99SBarry Smith 
558*47c6ae99SBarry Smith #undef __FUNCT__
559*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeRestoreAccess"
560*47c6ae99SBarry Smith /*@C
561*47c6ae99SBarry Smith     DMCompositeRestoreAccess - Returns the vectors obtained with DACompositeGetAccess()
562*47c6ae99SBarry Smith        representation.
563*47c6ae99SBarry Smith 
564*47c6ae99SBarry Smith     Collective on DMComposite
565*47c6ae99SBarry Smith 
566*47c6ae99SBarry Smith     Input Parameter:
567*47c6ae99SBarry Smith +    dm - the packer object
568*47c6ae99SBarry Smith .    gvec - the global vector
569*47c6ae99SBarry Smith -    ... - the individual sequential or parallel objects (arrays or vectors)
570*47c6ae99SBarry Smith 
571*47c6ae99SBarry Smith     Level: advanced
572*47c6ae99SBarry Smith 
573*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(),
574*47c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeScatter(),
575*47c6ae99SBarry Smith          DMCompositeRestoreAccess(), DACompositeGetAccess()
576*47c6ae99SBarry Smith 
577*47c6ae99SBarry Smith @*/
578*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeRestoreAccess(DM dm,Vec gvec,...)
579*47c6ae99SBarry Smith {
580*47c6ae99SBarry Smith   va_list                Argp;
581*47c6ae99SBarry Smith   PetscErrorCode         ierr;
582*47c6ae99SBarry Smith   struct DMCompositeLink *next;
583*47c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
584*47c6ae99SBarry Smith 
585*47c6ae99SBarry Smith   PetscFunctionBegin;
586*47c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
587*47c6ae99SBarry Smith   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
588*47c6ae99SBarry Smith   next = com->next;
589*47c6ae99SBarry Smith   if (!com->setup) {
590*47c6ae99SBarry Smith     ierr = DMCompositeSetUp(dm);CHKERRQ(ierr);
591*47c6ae99SBarry Smith   }
592*47c6ae99SBarry Smith 
593*47c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
594*47c6ae99SBarry Smith   va_start(Argp,gvec);
595*47c6ae99SBarry Smith   while (next) {
596*47c6ae99SBarry Smith     if (next->type == DMCOMPOSITE_ARRAY) {
597*47c6ae99SBarry Smith       PetscScalar **array;
598*47c6ae99SBarry Smith       array = va_arg(Argp, PetscScalar**);
599*47c6ae99SBarry Smith       ierr  = DMCompositeRestoreAccess_Array(dm,next,gvec,array);CHKERRQ(ierr);
600*47c6ae99SBarry Smith     } else if (next->type == DMCOMPOSITE_DM) {
601*47c6ae99SBarry Smith       Vec *vec;
602*47c6ae99SBarry Smith       vec  = va_arg(Argp, Vec*);
603*47c6ae99SBarry Smith       ierr = DMCompositeRestoreAccess_DM(dm,next,gvec,vec);CHKERRQ(ierr);
604*47c6ae99SBarry Smith     } else {
605*47c6ae99SBarry Smith       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
606*47c6ae99SBarry Smith     }
607*47c6ae99SBarry Smith     next = next->next;
608*47c6ae99SBarry Smith   }
609*47c6ae99SBarry Smith   va_end(Argp);
610*47c6ae99SBarry Smith   PetscFunctionReturn(0);
611*47c6ae99SBarry Smith }
612*47c6ae99SBarry Smith 
613*47c6ae99SBarry Smith #undef __FUNCT__
614*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeScatter"
615*47c6ae99SBarry Smith /*@C
616*47c6ae99SBarry Smith     DMCompositeScatter - Scatters from a global packed vector into its individual local vectors
617*47c6ae99SBarry Smith 
618*47c6ae99SBarry Smith     Collective on DMComposite
619*47c6ae99SBarry Smith 
620*47c6ae99SBarry Smith     Input Parameter:
621*47c6ae99SBarry Smith +    dm - the packer object
622*47c6ae99SBarry Smith .    gvec - the global vector
623*47c6ae99SBarry Smith -    ... - the individual sequential objects (arrays or vectors)
624*47c6ae99SBarry Smith 
625*47c6ae99SBarry Smith     Level: advanced
626*47c6ae99SBarry Smith 
627*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(),
628*47c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(),
629*47c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
630*47c6ae99SBarry Smith 
631*47c6ae99SBarry Smith @*/
632*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeScatter(DM dm,Vec gvec,...)
633*47c6ae99SBarry Smith {
634*47c6ae99SBarry Smith   va_list                Argp;
635*47c6ae99SBarry Smith   PetscErrorCode         ierr;
636*47c6ae99SBarry Smith   struct DMCompositeLink *next;
637*47c6ae99SBarry Smith   PetscInt               cnt = 3;
638*47c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
639*47c6ae99SBarry Smith 
640*47c6ae99SBarry Smith   PetscFunctionBegin;
641*47c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
642*47c6ae99SBarry Smith   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
643*47c6ae99SBarry Smith   next = com->next;
644*47c6ae99SBarry Smith   if (!com->setup) {
645*47c6ae99SBarry Smith     ierr = DMCompositeSetUp(dm);CHKERRQ(ierr);
646*47c6ae99SBarry Smith   }
647*47c6ae99SBarry Smith 
648*47c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
649*47c6ae99SBarry Smith   va_start(Argp,gvec);
650*47c6ae99SBarry Smith   while (next) {
651*47c6ae99SBarry Smith     if (next->type == DMCOMPOSITE_ARRAY) {
652*47c6ae99SBarry Smith       PetscScalar *array;
653*47c6ae99SBarry Smith       array = va_arg(Argp, PetscScalar*);
654*47c6ae99SBarry Smith       ierr = DMCompositeScatter_Array(dm,next,gvec,array);CHKERRQ(ierr);
655*47c6ae99SBarry Smith     } else if (next->type == DMCOMPOSITE_DM) {
656*47c6ae99SBarry Smith       Vec vec;
657*47c6ae99SBarry Smith       vec = va_arg(Argp, Vec);
658*47c6ae99SBarry Smith       PetscValidHeaderSpecific(vec,VEC_CLASSID,cnt);
659*47c6ae99SBarry Smith       ierr = DMCompositeScatter_DM(dm,next,gvec,vec);CHKERRQ(ierr);
660*47c6ae99SBarry Smith     } else {
661*47c6ae99SBarry Smith       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
662*47c6ae99SBarry Smith     }
663*47c6ae99SBarry Smith     cnt++;
664*47c6ae99SBarry Smith     next = next->next;
665*47c6ae99SBarry Smith   }
666*47c6ae99SBarry Smith   va_end(Argp);
667*47c6ae99SBarry Smith   PetscFunctionReturn(0);
668*47c6ae99SBarry Smith }
669*47c6ae99SBarry Smith 
670*47c6ae99SBarry Smith #undef __FUNCT__
671*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGather"
672*47c6ae99SBarry Smith /*@C
673*47c6ae99SBarry Smith     DMCompositeGather - Gathers into a global packed vector from its individual local vectors
674*47c6ae99SBarry Smith 
675*47c6ae99SBarry Smith     Collective on DMComposite
676*47c6ae99SBarry Smith 
677*47c6ae99SBarry Smith     Input Parameter:
678*47c6ae99SBarry Smith +    dm - the packer object
679*47c6ae99SBarry Smith .    gvec - the global vector
680*47c6ae99SBarry Smith -    ... - the individual sequential objects (arrays or vectors)
681*47c6ae99SBarry Smith 
682*47c6ae99SBarry Smith     Level: advanced
683*47c6ae99SBarry Smith 
684*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(),
685*47c6ae99SBarry Smith          DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(),
686*47c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
687*47c6ae99SBarry Smith 
688*47c6ae99SBarry Smith @*/
689*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGather(DM dm,Vec gvec,...)
690*47c6ae99SBarry Smith {
691*47c6ae99SBarry Smith   va_list                Argp;
692*47c6ae99SBarry Smith   PetscErrorCode         ierr;
693*47c6ae99SBarry Smith   struct DMCompositeLink *next;
694*47c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
695*47c6ae99SBarry Smith 
696*47c6ae99SBarry Smith   PetscFunctionBegin;
697*47c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
698*47c6ae99SBarry Smith   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
699*47c6ae99SBarry Smith   next = com->next;
700*47c6ae99SBarry Smith   if (!com->setup) {
701*47c6ae99SBarry Smith     ierr = DMCompositeSetUp(dm);CHKERRQ(ierr);
702*47c6ae99SBarry Smith   }
703*47c6ae99SBarry Smith 
704*47c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
705*47c6ae99SBarry Smith   va_start(Argp,gvec);
706*47c6ae99SBarry Smith   while (next) {
707*47c6ae99SBarry Smith     if (next->type == DMCOMPOSITE_ARRAY) {
708*47c6ae99SBarry Smith       PetscScalar *array;
709*47c6ae99SBarry Smith       array = va_arg(Argp, PetscScalar*);
710*47c6ae99SBarry Smith       ierr  = DMCompositeGather_Array(dm,next,gvec,array);CHKERRQ(ierr);
711*47c6ae99SBarry Smith     } else if (next->type == DMCOMPOSITE_DM) {
712*47c6ae99SBarry Smith       Vec vec;
713*47c6ae99SBarry Smith       vec = va_arg(Argp, Vec);
714*47c6ae99SBarry Smith       PetscValidHeaderSpecific(vec,VEC_CLASSID,3);
715*47c6ae99SBarry Smith       ierr = DMCompositeGather_DM(dm,next,gvec,vec);CHKERRQ(ierr);
716*47c6ae99SBarry Smith     } else {
717*47c6ae99SBarry Smith       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
718*47c6ae99SBarry Smith     }
719*47c6ae99SBarry Smith     next = next->next;
720*47c6ae99SBarry Smith   }
721*47c6ae99SBarry Smith   va_end(Argp);
722*47c6ae99SBarry Smith   PetscFunctionReturn(0);
723*47c6ae99SBarry Smith }
724*47c6ae99SBarry Smith 
725*47c6ae99SBarry Smith #undef __FUNCT__
726*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeAddArray"
727*47c6ae99SBarry Smith /*@C
728*47c6ae99SBarry Smith     DMCompositeAddArray - adds an "redundant" array to a DMComposite. The array values will
729*47c6ae99SBarry Smith        be stored in part of the array on process orank.
730*47c6ae99SBarry Smith 
731*47c6ae99SBarry Smith     Collective on DMComposite
732*47c6ae99SBarry Smith 
733*47c6ae99SBarry Smith     Input Parameter:
734*47c6ae99SBarry Smith +    dm - the packer object
735*47c6ae99SBarry Smith .    orank - the process on which the array entries officially live, this number must be
736*47c6ae99SBarry Smith              the same on all processes.
737*47c6ae99SBarry Smith -    n - the length of the array
738*47c6ae99SBarry Smith 
739*47c6ae99SBarry Smith     Level: advanced
740*47c6ae99SBarry Smith 
741*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeGather(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(),
742*47c6ae99SBarry Smith          DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(),
743*47c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
744*47c6ae99SBarry Smith 
745*47c6ae99SBarry Smith @*/
746*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeAddArray(DM dm,PetscMPIInt orank,PetscInt n)
747*47c6ae99SBarry Smith {
748*47c6ae99SBarry Smith   struct DMCompositeLink *mine,*next;
749*47c6ae99SBarry Smith   PetscErrorCode         ierr;
750*47c6ae99SBarry Smith   PetscMPIInt            rank;
751*47c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
752*47c6ae99SBarry Smith 
753*47c6ae99SBarry Smith   PetscFunctionBegin;
754*47c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
755*47c6ae99SBarry Smith   next = com->next;
756*47c6ae99SBarry Smith   if (com->setup) {
757*47c6ae99SBarry Smith     SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"Cannot add an array once you have used the DMComposite");
758*47c6ae99SBarry Smith   }
759*47c6ae99SBarry Smith #if defined(PETSC_USE_DEBUG)
760*47c6ae99SBarry Smith   {
761*47c6ae99SBarry Smith     PetscMPIInt orankmax;
762*47c6ae99SBarry Smith     ierr = MPI_Allreduce(&orank,&orankmax,1,MPI_INT,MPI_MAX,((PetscObject)dm)->comm);CHKERRQ(ierr);
763*47c6ae99SBarry Smith     if (orank != orankmax) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"orank %d must be equal on all processes, another process has value %d",orank,orankmax);
764*47c6ae99SBarry Smith   }
765*47c6ae99SBarry Smith #endif
766*47c6ae99SBarry Smith 
767*47c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
768*47c6ae99SBarry Smith   /* create new link */
769*47c6ae99SBarry Smith   ierr                = PetscNew(struct DMCompositeLink,&mine);CHKERRQ(ierr);
770*47c6ae99SBarry Smith   mine->n             = n;
771*47c6ae99SBarry Smith   mine->rank          = orank;
772*47c6ae99SBarry Smith   mine->dm            = PETSC_NULL;
773*47c6ae99SBarry Smith   mine->type          = DMCOMPOSITE_ARRAY;
774*47c6ae99SBarry Smith   mine->next          = PETSC_NULL;
775*47c6ae99SBarry Smith   if (rank == mine->rank) {com->n += n;com->nmine++;}
776*47c6ae99SBarry Smith 
777*47c6ae99SBarry Smith   /* add to end of list */
778*47c6ae99SBarry Smith   if (!next) {
779*47c6ae99SBarry Smith     com->next = mine;
780*47c6ae99SBarry Smith   } else {
781*47c6ae99SBarry Smith     while (next->next) next = next->next;
782*47c6ae99SBarry Smith     next->next = mine;
783*47c6ae99SBarry Smith   }
784*47c6ae99SBarry Smith   com->nredundant++;
785*47c6ae99SBarry Smith   PetscFunctionReturn(0);
786*47c6ae99SBarry Smith }
787*47c6ae99SBarry Smith 
788*47c6ae99SBarry Smith #undef __FUNCT__
789*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeAddDM"
790*47c6ae99SBarry Smith /*@C
791*47c6ae99SBarry Smith     DMCompositeAddDM - adds a DM (includes DA) vector to a DMComposite
792*47c6ae99SBarry Smith 
793*47c6ae99SBarry Smith     Collective on DMComposite
794*47c6ae99SBarry Smith 
795*47c6ae99SBarry Smith     Input Parameter:
796*47c6ae99SBarry Smith +    dm - the packer object
797*47c6ae99SBarry Smith -    dm - the DM object, if the DM is a da you will need to caste it with a (DM)
798*47c6ae99SBarry Smith 
799*47c6ae99SBarry Smith     Level: advanced
800*47c6ae99SBarry Smith 
801*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeGather(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(),
802*47c6ae99SBarry Smith          DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(),
803*47c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
804*47c6ae99SBarry Smith 
805*47c6ae99SBarry Smith @*/
806*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeAddDM(DM dmc,DM dm)
807*47c6ae99SBarry Smith {
808*47c6ae99SBarry Smith   PetscErrorCode         ierr;
809*47c6ae99SBarry Smith   PetscInt               n;
810*47c6ae99SBarry Smith   struct DMCompositeLink *mine,*next;
811*47c6ae99SBarry Smith   Vec                    global;
812*47c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dmc->data;
813*47c6ae99SBarry Smith 
814*47c6ae99SBarry Smith   PetscFunctionBegin;
815*47c6ae99SBarry Smith   PetscValidHeaderSpecific(dmc,DM_CLASSID,1);
816*47c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,2);
817*47c6ae99SBarry Smith   next = com->next;
818*47c6ae99SBarry Smith   if (com->setup) SETERRQ(((PetscObject)dmc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Cannot add a DA once you have used the DMComposite");
819*47c6ae99SBarry Smith 
820*47c6ae99SBarry Smith   /* create new link */
821*47c6ae99SBarry Smith   ierr = PetscNew(struct DMCompositeLink,&mine);CHKERRQ(ierr);
822*47c6ae99SBarry Smith   ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
823*47c6ae99SBarry Smith   ierr = DMGetGlobalVector(dm,&global);CHKERRQ(ierr);
824*47c6ae99SBarry Smith   ierr = VecGetLocalSize(global,&n);CHKERRQ(ierr);
825*47c6ae99SBarry Smith   ierr = DMRestoreGlobalVector(dm,&global);CHKERRQ(ierr);
826*47c6ae99SBarry Smith   mine->n      = n;
827*47c6ae99SBarry Smith   mine->dm     = dm;
828*47c6ae99SBarry Smith   mine->type   = DMCOMPOSITE_DM;
829*47c6ae99SBarry Smith   mine->next   = PETSC_NULL;
830*47c6ae99SBarry Smith   com->n       += n;
831*47c6ae99SBarry Smith 
832*47c6ae99SBarry Smith   /* add to end of list */
833*47c6ae99SBarry Smith   if (!next) {
834*47c6ae99SBarry Smith     com->next = mine;
835*47c6ae99SBarry Smith   } else {
836*47c6ae99SBarry Smith     while (next->next) next = next->next;
837*47c6ae99SBarry Smith     next->next = mine;
838*47c6ae99SBarry Smith   }
839*47c6ae99SBarry Smith   com->nDM++;
840*47c6ae99SBarry Smith   com->nmine++;
841*47c6ae99SBarry Smith   PetscFunctionReturn(0);
842*47c6ae99SBarry Smith }
843*47c6ae99SBarry Smith 
844*47c6ae99SBarry Smith extern PetscErrorCode PETSCDM_DLLEXPORT VecView_MPI(Vec,PetscViewer);
845*47c6ae99SBarry Smith EXTERN_C_BEGIN
846*47c6ae99SBarry Smith #undef __FUNCT__
847*47c6ae99SBarry Smith #define __FUNCT__ "VecView_DMComposite"
848*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT VecView_DMComposite(Vec gvec,PetscViewer viewer)
849*47c6ae99SBarry Smith {
850*47c6ae99SBarry Smith   DM                     dm;
851*47c6ae99SBarry Smith   PetscErrorCode         ierr;
852*47c6ae99SBarry Smith   struct DMCompositeLink *next;
853*47c6ae99SBarry Smith   PetscBool              isdraw;
854*47c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
855*47c6ae99SBarry Smith 
856*47c6ae99SBarry Smith   PetscFunctionBegin;
857*47c6ae99SBarry Smith   ierr = PetscObjectQuery((PetscObject)gvec,"DMComposite",(PetscObject*)&dm);CHKERRQ(ierr);
858*47c6ae99SBarry Smith   if (!dm) SETERRQ(((PetscObject)gvec)->comm,PETSC_ERR_ARG_WRONG,"Vector not generated from a DMComposite");
859*47c6ae99SBarry Smith   com = (DM_Composite*)dm->data;
860*47c6ae99SBarry Smith   next = com->next;
861*47c6ae99SBarry Smith 
862*47c6ae99SBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
863*47c6ae99SBarry Smith   if (!isdraw) {
864*47c6ae99SBarry Smith     /* do I really want to call this? */
865*47c6ae99SBarry Smith     ierr = VecView_MPI(gvec,viewer);CHKERRQ(ierr);
866*47c6ae99SBarry Smith   } else {
867*47c6ae99SBarry Smith     PetscInt cnt = 0;
868*47c6ae99SBarry Smith 
869*47c6ae99SBarry Smith     /* loop over packed objects, handling one at at time */
870*47c6ae99SBarry Smith     while (next) {
871*47c6ae99SBarry Smith       if (next->type == DMCOMPOSITE_ARRAY) {
872*47c6ae99SBarry Smith 	PetscScalar *array;
873*47c6ae99SBarry Smith 	ierr  = DMCompositeGetAccess_Array(dm,next,gvec,&array);CHKERRQ(ierr);
874*47c6ae99SBarry Smith 
875*47c6ae99SBarry Smith 	/*skip it for now */
876*47c6ae99SBarry Smith       } else if (next->type == DMCOMPOSITE_DM) {
877*47c6ae99SBarry Smith 	Vec      vec;
878*47c6ae99SBarry Smith         PetscInt bs;
879*47c6ae99SBarry Smith 
880*47c6ae99SBarry Smith 	ierr = DMCompositeGetAccess_DM(dm,next,gvec,&vec);CHKERRQ(ierr);
881*47c6ae99SBarry Smith 	ierr = VecView(vec,viewer);CHKERRQ(ierr);
882*47c6ae99SBarry Smith         ierr = VecGetBlockSize(vec,&bs);CHKERRQ(ierr);
883*47c6ae99SBarry Smith 	ierr = DMCompositeRestoreAccess_DM(dm,next,gvec,&vec);CHKERRQ(ierr);
884*47c6ae99SBarry Smith         ierr = PetscViewerDrawBaseAdd(viewer,bs);CHKERRQ(ierr);
885*47c6ae99SBarry Smith         cnt += bs;
886*47c6ae99SBarry Smith       } else {
887*47c6ae99SBarry Smith 	SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
888*47c6ae99SBarry Smith       }
889*47c6ae99SBarry Smith       next = next->next;
890*47c6ae99SBarry Smith     }
891*47c6ae99SBarry Smith     ierr = PetscViewerDrawBaseAdd(viewer,-cnt);CHKERRQ(ierr);
892*47c6ae99SBarry Smith   }
893*47c6ae99SBarry Smith   PetscFunctionReturn(0);
894*47c6ae99SBarry Smith }
895*47c6ae99SBarry Smith EXTERN_C_END
896*47c6ae99SBarry Smith 
897*47c6ae99SBarry Smith 
898*47c6ae99SBarry Smith #undef __FUNCT__
899*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeCreateGlobalVector"
900*47c6ae99SBarry Smith /*@C
901*47c6ae99SBarry Smith     DMCompositeCreateGlobalVector - Creates a vector of the correct size to be gathered into
902*47c6ae99SBarry Smith         by the packer.
903*47c6ae99SBarry Smith 
904*47c6ae99SBarry Smith     Collective on DMComposite
905*47c6ae99SBarry Smith 
906*47c6ae99SBarry Smith     Input Parameter:
907*47c6ae99SBarry Smith .    dm - the packer object
908*47c6ae99SBarry Smith 
909*47c6ae99SBarry Smith     Output Parameters:
910*47c6ae99SBarry Smith .   gvec - the global vector
911*47c6ae99SBarry Smith 
912*47c6ae99SBarry Smith     Level: advanced
913*47c6ae99SBarry Smith 
914*47c6ae99SBarry Smith     Notes: Once this has been created you cannot add additional arrays or vectors to be packed.
915*47c6ae99SBarry Smith 
916*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeScatter(),
917*47c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(),
918*47c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries(),
919*47c6ae99SBarry Smith          DMCompositeCreateLocalVector()
920*47c6ae99SBarry Smith 
921*47c6ae99SBarry Smith @*/
922*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeCreateGlobalVector(DM dm,Vec *gvec)
923*47c6ae99SBarry Smith {
924*47c6ae99SBarry Smith   PetscErrorCode         ierr;
925*47c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
926*47c6ae99SBarry Smith 
927*47c6ae99SBarry Smith   PetscFunctionBegin;
928*47c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
929*47c6ae99SBarry Smith   if (!com->setup) {
930*47c6ae99SBarry Smith     ierr = DMCompositeSetUp(dm);CHKERRQ(ierr);
931*47c6ae99SBarry Smith   }
932*47c6ae99SBarry Smith   ierr = VecCreateMPI(((PetscObject)dm)->comm,com->n,com->N,gvec);CHKERRQ(ierr);
933*47c6ae99SBarry Smith   ierr = PetscObjectCompose((PetscObject)*gvec,"DMComposite",(PetscObject)dm);CHKERRQ(ierr);
934*47c6ae99SBarry Smith   ierr = VecSetOperation(*gvec,VECOP_VIEW,(void(*)(void))VecView_DMComposite);CHKERRQ(ierr);
935*47c6ae99SBarry Smith   PetscFunctionReturn(0);
936*47c6ae99SBarry Smith }
937*47c6ae99SBarry Smith 
938*47c6ae99SBarry Smith #undef __FUNCT__
939*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeCreateLocalVector"
940*47c6ae99SBarry Smith /*@C
941*47c6ae99SBarry Smith     DMCompositeCreateLocalVector - Creates a vector of the correct size to contain all ghost points
942*47c6ae99SBarry Smith         and redundant arrays.
943*47c6ae99SBarry Smith 
944*47c6ae99SBarry Smith     Not Collective
945*47c6ae99SBarry Smith 
946*47c6ae99SBarry Smith     Input Parameter:
947*47c6ae99SBarry Smith .    dm - the packer object
948*47c6ae99SBarry Smith 
949*47c6ae99SBarry Smith     Output Parameters:
950*47c6ae99SBarry Smith .   lvec - the local vector
951*47c6ae99SBarry Smith 
952*47c6ae99SBarry Smith     Level: advanced
953*47c6ae99SBarry Smith 
954*47c6ae99SBarry Smith     Notes: Once this has been created you cannot add additional arrays or vectors to be packed.
955*47c6ae99SBarry Smith 
956*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeScatter(),
957*47c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(),
958*47c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries(),
959*47c6ae99SBarry Smith          DMCompositeCreateGlobalVector()
960*47c6ae99SBarry Smith 
961*47c6ae99SBarry Smith @*/
962*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeCreateLocalVector(DM dm,Vec *lvec)
963*47c6ae99SBarry Smith {
964*47c6ae99SBarry Smith   PetscErrorCode         ierr;
965*47c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
966*47c6ae99SBarry Smith 
967*47c6ae99SBarry Smith   PetscFunctionBegin;
968*47c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
969*47c6ae99SBarry Smith   if (!com->setup) {
970*47c6ae99SBarry Smith     ierr = DMCompositeSetUp(dm);CHKERRQ(ierr);
971*47c6ae99SBarry Smith   }
972*47c6ae99SBarry Smith   ierr = VecCreateSeq(((PetscObject)dm)->comm,com->nghost,lvec);CHKERRQ(ierr);
973*47c6ae99SBarry Smith   ierr = PetscObjectCompose((PetscObject)*lvec,"DMComposite",(PetscObject)dm);CHKERRQ(ierr);
974*47c6ae99SBarry Smith   PetscFunctionReturn(0);
975*47c6ae99SBarry Smith }
976*47c6ae99SBarry Smith 
977*47c6ae99SBarry Smith #undef __FUNCT__
978*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetLocalISs"
979*47c6ae99SBarry Smith /*@C
980*47c6ae99SBarry Smith     DMCompositeGetLocalISs - gets an IS for each DM/array in the DMComposite, include ghost points
981*47c6ae99SBarry Smith 
982*47c6ae99SBarry Smith     Collective on DMComposite
983*47c6ae99SBarry Smith 
984*47c6ae99SBarry Smith     Input Parameter:
985*47c6ae99SBarry Smith .    dm - the packer object
986*47c6ae99SBarry Smith 
987*47c6ae99SBarry Smith     Output Parameters:
988*47c6ae99SBarry Smith .    is - the individual indices for each packed vector/array. Note that this includes
989*47c6ae99SBarry Smith            all the ghost points that individual ghosted DA's may have. Also each process has an
990*47c6ae99SBarry Smith            is for EACH redundant array (not just the local redundant arrays).
991*47c6ae99SBarry Smith 
992*47c6ae99SBarry Smith     Level: advanced
993*47c6ae99SBarry Smith 
994*47c6ae99SBarry Smith     Notes:
995*47c6ae99SBarry Smith        The is entries should be destroyed with ISDestroy(), the is array should be freed with PetscFree()
996*47c6ae99SBarry Smith 
997*47c6ae99SBarry Smith        Use DMCompositeGetGlobalISs() for non-ghosted ISs.
998*47c6ae99SBarry Smith 
999*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(),
1000*47c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetAccess(), DMCompositeScatter(),
1001*47c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(),DMCompositeGetEntries()
1002*47c6ae99SBarry Smith 
1003*47c6ae99SBarry Smith @*/
1004*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGetGlobalIndices(DM dm,IS *is[])
1005*47c6ae99SBarry Smith {
1006*47c6ae99SBarry Smith   PetscErrorCode         ierr;
1007*47c6ae99SBarry Smith   PetscInt               i,*idx,n,cnt;
1008*47c6ae99SBarry Smith   struct DMCompositeLink *next;
1009*47c6ae99SBarry Smith   Vec                    global,dglobal;
1010*47c6ae99SBarry Smith   PF                     pf;
1011*47c6ae99SBarry Smith   PetscScalar            *array;
1012*47c6ae99SBarry Smith   PetscMPIInt            rank;
1013*47c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
1014*47c6ae99SBarry Smith 
1015*47c6ae99SBarry Smith   PetscFunctionBegin;
1016*47c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1017*47c6ae99SBarry Smith   ierr = PetscMalloc(com->nmine*sizeof(IS),is);CHKERRQ(ierr);
1018*47c6ae99SBarry Smith   next = com->next;
1019*47c6ae99SBarry Smith   ierr = DMCompositeCreateGlobalVector(dm,&global);CHKERRQ(ierr);
1020*47c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
1021*47c6ae99SBarry Smith 
1022*47c6ae99SBarry Smith   /* put 0 to N-1 into the global vector */
1023*47c6ae99SBarry Smith   ierr = PFCreate(PETSC_COMM_WORLD,1,1,&pf);CHKERRQ(ierr);
1024*47c6ae99SBarry Smith   ierr = PFSetType(pf,PFIDENTITY,PETSC_NULL);CHKERRQ(ierr);
1025*47c6ae99SBarry Smith   ierr = PFApplyVec(pf,PETSC_NULL,global);CHKERRQ(ierr);
1026*47c6ae99SBarry Smith   ierr = PFDestroy(pf);CHKERRQ(ierr);
1027*47c6ae99SBarry Smith 
1028*47c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
1029*47c6ae99SBarry Smith   cnt = 0;
1030*47c6ae99SBarry Smith   while (next) {
1031*47c6ae99SBarry Smith 
1032*47c6ae99SBarry Smith     if (next->type == DMCOMPOSITE_ARRAY) {
1033*47c6ae99SBarry Smith 
1034*47c6ae99SBarry Smith       ierr = PetscMalloc(next->n*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1035*47c6ae99SBarry Smith       if (rank == next->rank) {
1036*47c6ae99SBarry Smith         ierr   = VecGetArray(global,&array);CHKERRQ(ierr);
1037*47c6ae99SBarry Smith         array += next->rstart;
1038*47c6ae99SBarry Smith         for (i=0; i<next->n; i++) idx[i] = (PetscInt)PetscRealPart(array[i]);
1039*47c6ae99SBarry Smith         array -= next->rstart;
1040*47c6ae99SBarry Smith         ierr   = VecRestoreArray(global,&array);CHKERRQ(ierr);
1041*47c6ae99SBarry Smith       }
1042*47c6ae99SBarry Smith       ierr = MPI_Bcast(idx,next->n,MPIU_INT,next->rank,((PetscObject)dm)->comm);CHKERRQ(ierr);
1043*47c6ae99SBarry Smith       ierr = ISCreateGeneral(((PetscObject)dm)->comm,next->n,idx,PETSC_OWN_POINTER,&(*is)[cnt]);CHKERRQ(ierr);
1044*47c6ae99SBarry Smith     } else if (next->type == DMCOMPOSITE_DM) {
1045*47c6ae99SBarry Smith       Vec local;
1046*47c6ae99SBarry Smith 
1047*47c6ae99SBarry Smith       ierr   = DMCreateLocalVector(next->dm,&local);CHKERRQ(ierr);
1048*47c6ae99SBarry Smith       ierr   = VecGetArray(global,&array);CHKERRQ(ierr);
1049*47c6ae99SBarry Smith       array += next->rstart;
1050*47c6ae99SBarry Smith       ierr   = DMGetGlobalVector(next->dm,&dglobal);CHKERRQ(ierr);
1051*47c6ae99SBarry Smith       ierr   = VecPlaceArray(dglobal,array);CHKERRQ(ierr);
1052*47c6ae99SBarry Smith       ierr   = DMGlobalToLocalBegin(next->dm,dglobal,INSERT_VALUES,local);CHKERRQ(ierr);
1053*47c6ae99SBarry Smith       ierr   = DMGlobalToLocalEnd(next->dm,dglobal,INSERT_VALUES,local);CHKERRQ(ierr);
1054*47c6ae99SBarry Smith       array -= next->rstart;
1055*47c6ae99SBarry Smith       ierr   = VecRestoreArray(global,&array);CHKERRQ(ierr);
1056*47c6ae99SBarry Smith       ierr   = VecResetArray(dglobal);CHKERRQ(ierr);
1057*47c6ae99SBarry Smith       ierr   = DMRestoreGlobalVector(next->dm,&dglobal);CHKERRQ(ierr);
1058*47c6ae99SBarry Smith 
1059*47c6ae99SBarry Smith       ierr   = VecGetArray(local,&array);CHKERRQ(ierr);
1060*47c6ae99SBarry Smith       ierr   = VecGetSize(local,&n);CHKERRQ(ierr);
1061*47c6ae99SBarry Smith       ierr   = PetscMalloc(n*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1062*47c6ae99SBarry Smith       for (i=0; i<n; i++) idx[i] = (PetscInt)PetscRealPart(array[i]);
1063*47c6ae99SBarry Smith       ierr    = VecRestoreArray(local,&array);CHKERRQ(ierr);
1064*47c6ae99SBarry Smith       ierr    = VecDestroy(local);CHKERRQ(ierr);
1065*47c6ae99SBarry Smith       ierr    = ISCreateGeneral(((PetscObject)dm)->comm,next->n,idx,PETSC_OWN_POINTER,&(*is)[cnt]);CHKERRQ(ierr);
1066*47c6ae99SBarry Smith 
1067*47c6ae99SBarry Smith     } else SETERRQ(((PetscObject)global)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1068*47c6ae99SBarry Smith     next = next->next;
1069*47c6ae99SBarry Smith     cnt++;
1070*47c6ae99SBarry Smith   }
1071*47c6ae99SBarry Smith   ierr = VecDestroy(global);CHKERRQ(ierr);
1072*47c6ae99SBarry Smith   PetscFunctionReturn(0);
1073*47c6ae99SBarry Smith }
1074*47c6ae99SBarry Smith 
1075*47c6ae99SBarry Smith #undef __FUNCT__
1076*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetGlobalISs"
1077*47c6ae99SBarry Smith /*@C
1078*47c6ae99SBarry Smith     DMCompositeGetGlobalISs - Gets the index sets for each composed object
1079*47c6ae99SBarry Smith 
1080*47c6ae99SBarry Smith     Collective on DMComposite
1081*47c6ae99SBarry Smith 
1082*47c6ae99SBarry Smith     Input Parameter:
1083*47c6ae99SBarry Smith .    dm - the packer object
1084*47c6ae99SBarry Smith 
1085*47c6ae99SBarry Smith     Output Parameters:
1086*47c6ae99SBarry Smith .    is - the array of index sets
1087*47c6ae99SBarry Smith 
1088*47c6ae99SBarry Smith     Level: advanced
1089*47c6ae99SBarry Smith 
1090*47c6ae99SBarry Smith     Notes:
1091*47c6ae99SBarry Smith        The is entries should be destroyed with ISDestroy(), the is array should be freed with PetscFree()
1092*47c6ae99SBarry Smith 
1093*47c6ae99SBarry Smith        The number of IS on each process will/may be different when redundant arrays are used
1094*47c6ae99SBarry Smith 
1095*47c6ae99SBarry Smith        These could be used to extract a subset of vector entries for a "multi-physics" preconditioner
1096*47c6ae99SBarry Smith 
1097*47c6ae99SBarry Smith        Use DMCompositeGetLocalISs() for index sets that include ghost points
1098*47c6ae99SBarry Smith 
1099*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(),
1100*47c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetAccess(), DMCompositeScatter(),
1101*47c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(),DMCompositeGetEntries()
1102*47c6ae99SBarry Smith 
1103*47c6ae99SBarry Smith @*/
1104*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGetGlobalISs(DM dm,IS *is[])
1105*47c6ae99SBarry Smith {
1106*47c6ae99SBarry Smith   PetscErrorCode         ierr;
1107*47c6ae99SBarry Smith   PetscInt               cnt = 0,*idx,i;
1108*47c6ae99SBarry Smith   struct DMCompositeLink *next;
1109*47c6ae99SBarry Smith   PetscMPIInt            rank;
1110*47c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
1111*47c6ae99SBarry Smith 
1112*47c6ae99SBarry Smith   PetscFunctionBegin;
1113*47c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1114*47c6ae99SBarry Smith   ierr = PetscMalloc(com->nmine*sizeof(IS),is);CHKERRQ(ierr);
1115*47c6ae99SBarry Smith   next = com->next;
1116*47c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
1117*47c6ae99SBarry Smith 
1118*47c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
1119*47c6ae99SBarry Smith   while (next) {
1120*47c6ae99SBarry Smith 
1121*47c6ae99SBarry Smith     if (next->type == DMCOMPOSITE_ARRAY) {
1122*47c6ae99SBarry Smith 
1123*47c6ae99SBarry Smith       if (rank == next->rank) {
1124*47c6ae99SBarry Smith         ierr = PetscMalloc(next->n*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1125*47c6ae99SBarry Smith         for (i=0; i<next->n; i++) idx[i] = next->grstart + i;
1126*47c6ae99SBarry Smith         ierr = ISCreateGeneral(((PetscObject)dm)->comm,next->n,idx,PETSC_OWN_POINTER,&(*is)[cnt]);CHKERRQ(ierr);
1127*47c6ae99SBarry Smith         cnt++;
1128*47c6ae99SBarry Smith       }
1129*47c6ae99SBarry Smith 
1130*47c6ae99SBarry Smith     } else if (next->type == DMCOMPOSITE_DM) {
1131*47c6ae99SBarry Smith       ierr = PetscMalloc(next->n*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1132*47c6ae99SBarry Smith       for (i=0; i<next->n; i++) idx[i] = next->grstart + i;
1133*47c6ae99SBarry Smith       ierr = ISCreateGeneral(((PetscObject)dm)->comm,next->n,idx,PETSC_OWN_POINTER,&(*is)[cnt]);CHKERRQ(ierr);
1134*47c6ae99SBarry Smith       cnt++;
1135*47c6ae99SBarry Smith     } else {
1136*47c6ae99SBarry Smith       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1137*47c6ae99SBarry Smith     }
1138*47c6ae99SBarry Smith     next = next->next;
1139*47c6ae99SBarry Smith   }
1140*47c6ae99SBarry Smith   PetscFunctionReturn(0);
1141*47c6ae99SBarry Smith }
1142*47c6ae99SBarry Smith 
1143*47c6ae99SBarry Smith /* -------------------------------------------------------------------------------------*/
1144*47c6ae99SBarry Smith #undef __FUNCT__
1145*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetLocalVectors_Array"
1146*47c6ae99SBarry Smith PetscErrorCode DMCompositeGetLocalVectors_Array(DM dm,struct DMCompositeLink *mine,PetscScalar **array)
1147*47c6ae99SBarry Smith {
1148*47c6ae99SBarry Smith   PetscErrorCode ierr;
1149*47c6ae99SBarry Smith   PetscFunctionBegin;
1150*47c6ae99SBarry Smith   if (array) {
1151*47c6ae99SBarry Smith     ierr = PetscMalloc(mine->n*sizeof(PetscScalar),array);CHKERRQ(ierr);
1152*47c6ae99SBarry Smith   }
1153*47c6ae99SBarry Smith   PetscFunctionReturn(0);
1154*47c6ae99SBarry Smith }
1155*47c6ae99SBarry Smith 
1156*47c6ae99SBarry Smith #undef __FUNCT__
1157*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetLocalVectors_DM"
1158*47c6ae99SBarry Smith PetscErrorCode DMCompositeGetLocalVectors_DM(DM dm,struct DMCompositeLink *mine,Vec *local)
1159*47c6ae99SBarry Smith {
1160*47c6ae99SBarry Smith   PetscErrorCode ierr;
1161*47c6ae99SBarry Smith   PetscFunctionBegin;
1162*47c6ae99SBarry Smith   if (local) {
1163*47c6ae99SBarry Smith     ierr = DMGetLocalVector(mine->dm,local);CHKERRQ(ierr);
1164*47c6ae99SBarry Smith   }
1165*47c6ae99SBarry Smith   PetscFunctionReturn(0);
1166*47c6ae99SBarry Smith }
1167*47c6ae99SBarry Smith 
1168*47c6ae99SBarry Smith #undef __FUNCT__
1169*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeRestoreLocalVectors_Array"
1170*47c6ae99SBarry Smith PetscErrorCode DMCompositeRestoreLocalVectors_Array(DM dm,struct DMCompositeLink *mine,PetscScalar **array)
1171*47c6ae99SBarry Smith {
1172*47c6ae99SBarry Smith   PetscErrorCode ierr;
1173*47c6ae99SBarry Smith   PetscFunctionBegin;
1174*47c6ae99SBarry Smith   if (array) {
1175*47c6ae99SBarry Smith     ierr = PetscFree(*array);CHKERRQ(ierr);
1176*47c6ae99SBarry Smith   }
1177*47c6ae99SBarry Smith   PetscFunctionReturn(0);
1178*47c6ae99SBarry Smith }
1179*47c6ae99SBarry Smith 
1180*47c6ae99SBarry Smith #undef __FUNCT__
1181*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeRestoreLocalVectors_DM"
1182*47c6ae99SBarry Smith PetscErrorCode DMCompositeRestoreLocalVectors_DM(DM dm,struct DMCompositeLink *mine,Vec *local)
1183*47c6ae99SBarry Smith {
1184*47c6ae99SBarry Smith   PetscErrorCode ierr;
1185*47c6ae99SBarry Smith   PetscFunctionBegin;
1186*47c6ae99SBarry Smith   if (local) {
1187*47c6ae99SBarry Smith     ierr = DMRestoreLocalVector(mine->dm,local);CHKERRQ(ierr);
1188*47c6ae99SBarry Smith   }
1189*47c6ae99SBarry Smith   PetscFunctionReturn(0);
1190*47c6ae99SBarry Smith }
1191*47c6ae99SBarry Smith 
1192*47c6ae99SBarry Smith #undef __FUNCT__
1193*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetLocalVectors"
1194*47c6ae99SBarry Smith /*@C
1195*47c6ae99SBarry Smith     DMCompositeGetLocalVectors - Gets local vectors and arrays for each part of a DMComposite.
1196*47c6ae99SBarry Smith        Use DMCompositeRestoreLocalVectors() to return them.
1197*47c6ae99SBarry Smith 
1198*47c6ae99SBarry Smith     Not Collective
1199*47c6ae99SBarry Smith 
1200*47c6ae99SBarry Smith     Input Parameter:
1201*47c6ae99SBarry Smith .    dm - the packer object
1202*47c6ae99SBarry Smith 
1203*47c6ae99SBarry Smith     Output Parameter:
1204*47c6ae99SBarry Smith .    ... - the individual sequential objects (arrays or vectors)
1205*47c6ae99SBarry Smith 
1206*47c6ae99SBarry Smith     Level: advanced
1207*47c6ae99SBarry Smith 
1208*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(),
1209*47c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(),
1210*47c6ae99SBarry Smith          DMCompositeRestoreLocalVectors(), DMCompositeScatter(), DMCompositeGetEntries()
1211*47c6ae99SBarry Smith 
1212*47c6ae99SBarry Smith @*/
1213*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGetLocalVectors(DM dm,...)
1214*47c6ae99SBarry Smith {
1215*47c6ae99SBarry Smith   va_list                Argp;
1216*47c6ae99SBarry Smith   PetscErrorCode         ierr;
1217*47c6ae99SBarry Smith   struct DMCompositeLink *next;
1218*47c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
1219*47c6ae99SBarry Smith 
1220*47c6ae99SBarry Smith   PetscFunctionBegin;
1221*47c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1222*47c6ae99SBarry Smith   next = com->next;
1223*47c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
1224*47c6ae99SBarry Smith   va_start(Argp,dm);
1225*47c6ae99SBarry Smith   while (next) {
1226*47c6ae99SBarry Smith     if (next->type == DMCOMPOSITE_ARRAY) {
1227*47c6ae99SBarry Smith       PetscScalar **array;
1228*47c6ae99SBarry Smith       array = va_arg(Argp, PetscScalar**);
1229*47c6ae99SBarry Smith       ierr = DMCompositeGetLocalVectors_Array(dm,next,array);CHKERRQ(ierr);
1230*47c6ae99SBarry Smith     } else if (next->type == DMCOMPOSITE_DM) {
1231*47c6ae99SBarry Smith       Vec *vec;
1232*47c6ae99SBarry Smith       vec = va_arg(Argp, Vec*);
1233*47c6ae99SBarry Smith       ierr = DMCompositeGetLocalVectors_DM(dm,next,vec);CHKERRQ(ierr);
1234*47c6ae99SBarry Smith     } else {
1235*47c6ae99SBarry Smith       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1236*47c6ae99SBarry Smith     }
1237*47c6ae99SBarry Smith     next = next->next;
1238*47c6ae99SBarry Smith   }
1239*47c6ae99SBarry Smith   va_end(Argp);
1240*47c6ae99SBarry Smith   PetscFunctionReturn(0);
1241*47c6ae99SBarry Smith }
1242*47c6ae99SBarry Smith 
1243*47c6ae99SBarry Smith #undef __FUNCT__
1244*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeRestoreLocalVectors"
1245*47c6ae99SBarry Smith /*@C
1246*47c6ae99SBarry Smith     DMCompositeRestoreLocalVectors - Restores local vectors and arrays for each part of a DMComposite.
1247*47c6ae99SBarry Smith 
1248*47c6ae99SBarry Smith     Not Collective
1249*47c6ae99SBarry Smith 
1250*47c6ae99SBarry Smith     Input Parameter:
1251*47c6ae99SBarry Smith .    dm - the packer object
1252*47c6ae99SBarry Smith 
1253*47c6ae99SBarry Smith     Output Parameter:
1254*47c6ae99SBarry Smith .    ... - the individual sequential objects (arrays or vectors)
1255*47c6ae99SBarry Smith 
1256*47c6ae99SBarry Smith     Level: advanced
1257*47c6ae99SBarry Smith 
1258*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(),
1259*47c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(),
1260*47c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeScatter(), DMCompositeGetEntries()
1261*47c6ae99SBarry Smith 
1262*47c6ae99SBarry Smith @*/
1263*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeRestoreLocalVectors(DM dm,...)
1264*47c6ae99SBarry Smith {
1265*47c6ae99SBarry Smith   va_list                Argp;
1266*47c6ae99SBarry Smith   PetscErrorCode         ierr;
1267*47c6ae99SBarry Smith   struct DMCompositeLink *next;
1268*47c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
1269*47c6ae99SBarry Smith 
1270*47c6ae99SBarry Smith   PetscFunctionBegin;
1271*47c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1272*47c6ae99SBarry Smith   next = com->next;
1273*47c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
1274*47c6ae99SBarry Smith   va_start(Argp,dm);
1275*47c6ae99SBarry Smith   while (next) {
1276*47c6ae99SBarry Smith     if (next->type == DMCOMPOSITE_ARRAY) {
1277*47c6ae99SBarry Smith       PetscScalar **array;
1278*47c6ae99SBarry Smith       array = va_arg(Argp, PetscScalar**);
1279*47c6ae99SBarry Smith       ierr = DMCompositeRestoreLocalVectors_Array(dm,next,array);CHKERRQ(ierr);
1280*47c6ae99SBarry Smith     } else if (next->type == DMCOMPOSITE_DM) {
1281*47c6ae99SBarry Smith       Vec *vec;
1282*47c6ae99SBarry Smith       vec = va_arg(Argp, Vec*);
1283*47c6ae99SBarry Smith       ierr = DMCompositeRestoreLocalVectors_DM(dm,next,vec);CHKERRQ(ierr);
1284*47c6ae99SBarry Smith     } else {
1285*47c6ae99SBarry Smith       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1286*47c6ae99SBarry Smith     }
1287*47c6ae99SBarry Smith     next = next->next;
1288*47c6ae99SBarry Smith   }
1289*47c6ae99SBarry Smith   va_end(Argp);
1290*47c6ae99SBarry Smith   PetscFunctionReturn(0);
1291*47c6ae99SBarry Smith }
1292*47c6ae99SBarry Smith 
1293*47c6ae99SBarry Smith /* -------------------------------------------------------------------------------------*/
1294*47c6ae99SBarry Smith #undef __FUNCT__
1295*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetEntries_Array"
1296*47c6ae99SBarry Smith PetscErrorCode DMCompositeGetEntries_Array(DM dm,struct DMCompositeLink *mine,PetscInt *n)
1297*47c6ae99SBarry Smith {
1298*47c6ae99SBarry Smith   PetscFunctionBegin;
1299*47c6ae99SBarry Smith   if (n) *n = mine->n;
1300*47c6ae99SBarry Smith   PetscFunctionReturn(0);
1301*47c6ae99SBarry Smith }
1302*47c6ae99SBarry Smith 
1303*47c6ae99SBarry Smith #undef __FUNCT__
1304*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetEntries_DM"
1305*47c6ae99SBarry Smith PetscErrorCode DMCompositeGetEntries_DM(DM dmi,struct DMCompositeLink *mine,DM *dm)
1306*47c6ae99SBarry Smith {
1307*47c6ae99SBarry Smith   PetscFunctionBegin;
1308*47c6ae99SBarry Smith   if (dm) *dm = mine->dm;
1309*47c6ae99SBarry Smith   PetscFunctionReturn(0);
1310*47c6ae99SBarry Smith }
1311*47c6ae99SBarry Smith 
1312*47c6ae99SBarry Smith #undef __FUNCT__
1313*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetEntries"
1314*47c6ae99SBarry Smith /*@C
1315*47c6ae99SBarry Smith     DMCompositeGetEntries - Gets the DA, redundant size, etc for each entry in a DMComposite.
1316*47c6ae99SBarry Smith 
1317*47c6ae99SBarry Smith     Not Collective
1318*47c6ae99SBarry Smith 
1319*47c6ae99SBarry Smith     Input Parameter:
1320*47c6ae99SBarry Smith .    dm - the packer object
1321*47c6ae99SBarry Smith 
1322*47c6ae99SBarry Smith     Output Parameter:
1323*47c6ae99SBarry Smith .    ... - the individual entries, DAs or integer sizes)
1324*47c6ae99SBarry Smith 
1325*47c6ae99SBarry Smith     Level: advanced
1326*47c6ae99SBarry Smith 
1327*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(),
1328*47c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(),
1329*47c6ae99SBarry Smith          DMCompositeRestoreLocalVectors(), DMCompositeGetLocalVectors(),  DMCompositeScatter(),
1330*47c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors()
1331*47c6ae99SBarry Smith 
1332*47c6ae99SBarry Smith @*/
1333*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGetEntries(DM dm,...)
1334*47c6ae99SBarry Smith {
1335*47c6ae99SBarry Smith   va_list                Argp;
1336*47c6ae99SBarry Smith   PetscErrorCode         ierr;
1337*47c6ae99SBarry Smith   struct DMCompositeLink *next;
1338*47c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
1339*47c6ae99SBarry Smith 
1340*47c6ae99SBarry Smith   PetscFunctionBegin;
1341*47c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1342*47c6ae99SBarry Smith   next = com->next;
1343*47c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
1344*47c6ae99SBarry Smith   va_start(Argp,dm);
1345*47c6ae99SBarry Smith   while (next) {
1346*47c6ae99SBarry Smith     if (next->type == DMCOMPOSITE_ARRAY) {
1347*47c6ae99SBarry Smith       PetscInt *n;
1348*47c6ae99SBarry Smith       n = va_arg(Argp, PetscInt*);
1349*47c6ae99SBarry Smith       ierr = DMCompositeGetEntries_Array(dm,next,n);CHKERRQ(ierr);
1350*47c6ae99SBarry Smith     } else if (next->type == DMCOMPOSITE_DM) {
1351*47c6ae99SBarry Smith       DM *dmn;
1352*47c6ae99SBarry Smith       dmn = va_arg(Argp, DM*);
1353*47c6ae99SBarry Smith       ierr = DMCompositeGetEntries_DM(dm,next,dmn);CHKERRQ(ierr);
1354*47c6ae99SBarry Smith     } else {
1355*47c6ae99SBarry Smith       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1356*47c6ae99SBarry Smith     }
1357*47c6ae99SBarry Smith     next = next->next;
1358*47c6ae99SBarry Smith   }
1359*47c6ae99SBarry Smith   va_end(Argp);
1360*47c6ae99SBarry Smith   PetscFunctionReturn(0);
1361*47c6ae99SBarry Smith }
1362*47c6ae99SBarry Smith 
1363*47c6ae99SBarry Smith #undef __FUNCT__
1364*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeRefine"
1365*47c6ae99SBarry Smith /*@C
1366*47c6ae99SBarry Smith     DMCompositeRefine - Refines a DM by refining all of its DAs
1367*47c6ae99SBarry Smith 
1368*47c6ae99SBarry Smith     Collective on DMComposite
1369*47c6ae99SBarry Smith 
1370*47c6ae99SBarry Smith     Input Parameters:
1371*47c6ae99SBarry Smith +    dm - the packer object
1372*47c6ae99SBarry Smith -    comm - communicator to contain the new DM object, usually PETSC_NULL
1373*47c6ae99SBarry Smith 
1374*47c6ae99SBarry Smith     Output Parameter:
1375*47c6ae99SBarry Smith .    fine - new packer
1376*47c6ae99SBarry Smith 
1377*47c6ae99SBarry Smith     Level: advanced
1378*47c6ae99SBarry Smith 
1379*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(),
1380*47c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(),
1381*47c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(),  DMCompositeScatter(),
1382*47c6ae99SBarry Smith          DMCompositeGetEntries()
1383*47c6ae99SBarry Smith 
1384*47c6ae99SBarry Smith @*/
1385*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeRefine(DM dmi,MPI_Comm comm,DM *fine)
1386*47c6ae99SBarry Smith {
1387*47c6ae99SBarry Smith   PetscErrorCode         ierr;
1388*47c6ae99SBarry Smith   struct DMCompositeLink *next;
1389*47c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dmi->data;
1390*47c6ae99SBarry Smith   DM                     dm;
1391*47c6ae99SBarry Smith 
1392*47c6ae99SBarry Smith   PetscFunctionBegin;
1393*47c6ae99SBarry Smith   PetscValidHeaderSpecific(dmi,DM_CLASSID,1);
1394*47c6ae99SBarry Smith   next = com->next;
1395*47c6ae99SBarry Smith   ierr = DMCompositeCreate(comm,fine);CHKERRQ(ierr);
1396*47c6ae99SBarry Smith 
1397*47c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
1398*47c6ae99SBarry Smith   while (next) {
1399*47c6ae99SBarry Smith     if (next->type == DMCOMPOSITE_ARRAY) {
1400*47c6ae99SBarry Smith       ierr = DMCompositeAddArray(*fine,next->rank,next->n);CHKERRQ(ierr);
1401*47c6ae99SBarry Smith     } else if (next->type == DMCOMPOSITE_DM) {
1402*47c6ae99SBarry Smith       ierr = DMRefine(next->dm,comm,&dm);CHKERRQ(ierr);
1403*47c6ae99SBarry Smith       ierr = DMCompositeAddDM(*fine,dm);CHKERRQ(ierr);
1404*47c6ae99SBarry Smith       ierr = PetscObjectDereference((PetscObject)dm);CHKERRQ(ierr);
1405*47c6ae99SBarry Smith     } else {
1406*47c6ae99SBarry Smith       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1407*47c6ae99SBarry Smith     }
1408*47c6ae99SBarry Smith     next = next->next;
1409*47c6ae99SBarry Smith   }
1410*47c6ae99SBarry Smith   PetscFunctionReturn(0);
1411*47c6ae99SBarry Smith }
1412*47c6ae99SBarry Smith 
1413*47c6ae99SBarry Smith #include "petscmat.h"
1414*47c6ae99SBarry Smith 
1415*47c6ae99SBarry Smith struct MatPackLink {
1416*47c6ae99SBarry Smith   Mat                A;
1417*47c6ae99SBarry Smith   struct MatPackLink *next;
1418*47c6ae99SBarry Smith };
1419*47c6ae99SBarry Smith 
1420*47c6ae99SBarry Smith struct MatPack {
1421*47c6ae99SBarry Smith   DM                 right,left;
1422*47c6ae99SBarry Smith   struct MatPackLink *next;
1423*47c6ae99SBarry Smith };
1424*47c6ae99SBarry Smith 
1425*47c6ae99SBarry Smith #undef __FUNCT__
1426*47c6ae99SBarry Smith #define __FUNCT__ "MatMultBoth_Shell_Pack"
1427*47c6ae99SBarry Smith PetscErrorCode MatMultBoth_Shell_Pack(Mat A,Vec x,Vec y,PetscBool  add)
1428*47c6ae99SBarry Smith {
1429*47c6ae99SBarry Smith   struct MatPack         *mpack;
1430*47c6ae99SBarry Smith   struct DMCompositeLink *xnext,*ynext;
1431*47c6ae99SBarry Smith   struct MatPackLink     *anext;
1432*47c6ae99SBarry Smith   PetscScalar            *xarray,*yarray;
1433*47c6ae99SBarry Smith   PetscErrorCode         ierr;
1434*47c6ae99SBarry Smith   PetscInt               i;
1435*47c6ae99SBarry Smith   Vec                    xglobal,yglobal;
1436*47c6ae99SBarry Smith   PetscMPIInt            rank;
1437*47c6ae99SBarry Smith   DM_Composite           *comright;
1438*47c6ae99SBarry Smith   DM_Composite           *comleft;
1439*47c6ae99SBarry Smith 
1440*47c6ae99SBarry Smith   PetscFunctionBegin;
1441*47c6ae99SBarry Smith   ierr = MatShellGetContext(A,(void**)&mpack);CHKERRQ(ierr);
1442*47c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)mpack->right)->comm,&rank);CHKERRQ(ierr);
1443*47c6ae99SBarry Smith   comright = (DM_Composite*)mpack->right->data;
1444*47c6ae99SBarry Smith   comleft = (DM_Composite*)mpack->left->data;
1445*47c6ae99SBarry Smith   xnext = comright->next;
1446*47c6ae99SBarry Smith   ynext = comleft->next;
1447*47c6ae99SBarry Smith   anext = mpack->next;
1448*47c6ae99SBarry Smith 
1449*47c6ae99SBarry Smith   while (xnext) {
1450*47c6ae99SBarry Smith     if (xnext->type == DMCOMPOSITE_ARRAY) {
1451*47c6ae99SBarry Smith       if (rank == xnext->rank) {
1452*47c6ae99SBarry Smith         ierr    = VecGetArray(x,&xarray);CHKERRQ(ierr);
1453*47c6ae99SBarry Smith         ierr    = VecGetArray(y,&yarray);CHKERRQ(ierr);
1454*47c6ae99SBarry Smith         if (add) {
1455*47c6ae99SBarry Smith           for (i=0; i<xnext->n; i++) {
1456*47c6ae99SBarry Smith             yarray[ynext->rstart+i] += xarray[xnext->rstart+i];
1457*47c6ae99SBarry Smith           }
1458*47c6ae99SBarry Smith         } else {
1459*47c6ae99SBarry Smith           ierr    = PetscMemcpy(yarray+ynext->rstart,xarray+xnext->rstart,xnext->n*sizeof(PetscScalar));CHKERRQ(ierr);
1460*47c6ae99SBarry Smith         }
1461*47c6ae99SBarry Smith         ierr    = VecRestoreArray(x,&xarray);CHKERRQ(ierr);
1462*47c6ae99SBarry Smith         ierr    = VecRestoreArray(y,&yarray);CHKERRQ(ierr);
1463*47c6ae99SBarry Smith       }
1464*47c6ae99SBarry Smith     } else if (xnext->type == DMCOMPOSITE_DM) {
1465*47c6ae99SBarry Smith       ierr  = VecGetArray(x,&xarray);CHKERRQ(ierr);
1466*47c6ae99SBarry Smith       ierr  = VecGetArray(y,&yarray);CHKERRQ(ierr);
1467*47c6ae99SBarry Smith       ierr  = DMGetGlobalVector(xnext->dm,&xglobal);CHKERRQ(ierr);
1468*47c6ae99SBarry Smith       ierr  = DMGetGlobalVector(ynext->dm,&yglobal);CHKERRQ(ierr);
1469*47c6ae99SBarry Smith       ierr  = VecPlaceArray(xglobal,xarray+xnext->rstart);CHKERRQ(ierr);
1470*47c6ae99SBarry Smith       ierr  = VecPlaceArray(yglobal,yarray+ynext->rstart);CHKERRQ(ierr);
1471*47c6ae99SBarry Smith       if (add) {
1472*47c6ae99SBarry Smith         ierr  = MatMultAdd(anext->A,xglobal,yglobal,yglobal);CHKERRQ(ierr);
1473*47c6ae99SBarry Smith       } else {
1474*47c6ae99SBarry Smith         ierr  = MatMult(anext->A,xglobal,yglobal);CHKERRQ(ierr);
1475*47c6ae99SBarry Smith       }
1476*47c6ae99SBarry Smith       ierr  = VecRestoreArray(x,&xarray);CHKERRQ(ierr);
1477*47c6ae99SBarry Smith       ierr  = VecRestoreArray(y,&yarray);CHKERRQ(ierr);
1478*47c6ae99SBarry Smith       ierr  = VecResetArray(xglobal);CHKERRQ(ierr);
1479*47c6ae99SBarry Smith       ierr  = VecResetArray(yglobal);CHKERRQ(ierr);
1480*47c6ae99SBarry Smith       ierr  = DMRestoreGlobalVector(xnext->dm,&xglobal);CHKERRQ(ierr);
1481*47c6ae99SBarry Smith       ierr  = DMRestoreGlobalVector(ynext->dm,&yglobal);CHKERRQ(ierr);
1482*47c6ae99SBarry Smith       anext = anext->next;
1483*47c6ae99SBarry Smith     } else {
1484*47c6ae99SBarry Smith       SETERRQ(((PetscObject)A)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1485*47c6ae99SBarry Smith     }
1486*47c6ae99SBarry Smith     xnext = xnext->next;
1487*47c6ae99SBarry Smith     ynext = ynext->next;
1488*47c6ae99SBarry Smith   }
1489*47c6ae99SBarry Smith   PetscFunctionReturn(0);
1490*47c6ae99SBarry Smith }
1491*47c6ae99SBarry Smith 
1492*47c6ae99SBarry Smith #undef __FUNCT__
1493*47c6ae99SBarry Smith #define __FUNCT__ "MatMultAdd_Shell_Pack"
1494*47c6ae99SBarry Smith PetscErrorCode MatMultAdd_Shell_Pack(Mat A,Vec x,Vec y,Vec z)
1495*47c6ae99SBarry Smith {
1496*47c6ae99SBarry Smith   PetscErrorCode ierr;
1497*47c6ae99SBarry Smith   PetscFunctionBegin;
1498*47c6ae99SBarry Smith   if (z != y) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_SUP,"Handles y == z only");
1499*47c6ae99SBarry Smith   ierr = MatMultBoth_Shell_Pack(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
1500*47c6ae99SBarry Smith   PetscFunctionReturn(0);
1501*47c6ae99SBarry Smith }
1502*47c6ae99SBarry Smith 
1503*47c6ae99SBarry Smith #undef __FUNCT__
1504*47c6ae99SBarry Smith #define __FUNCT__ "MatMult_Shell_Pack"
1505*47c6ae99SBarry Smith PetscErrorCode MatMult_Shell_Pack(Mat A,Vec x,Vec y)
1506*47c6ae99SBarry Smith {
1507*47c6ae99SBarry Smith   PetscErrorCode ierr;
1508*47c6ae99SBarry Smith   PetscFunctionBegin;
1509*47c6ae99SBarry Smith   ierr = MatMultBoth_Shell_Pack(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
1510*47c6ae99SBarry Smith   PetscFunctionReturn(0);
1511*47c6ae99SBarry Smith }
1512*47c6ae99SBarry Smith 
1513*47c6ae99SBarry Smith #undef __FUNCT__
1514*47c6ae99SBarry Smith #define __FUNCT__ "MatMultTranspose_Shell_Pack"
1515*47c6ae99SBarry Smith PetscErrorCode MatMultTranspose_Shell_Pack(Mat A,Vec x,Vec y)
1516*47c6ae99SBarry Smith {
1517*47c6ae99SBarry Smith   struct MatPack         *mpack;
1518*47c6ae99SBarry Smith   struct DMCompositeLink *xnext,*ynext;
1519*47c6ae99SBarry Smith   struct MatPackLink     *anext;
1520*47c6ae99SBarry Smith   PetscScalar            *xarray,*yarray;
1521*47c6ae99SBarry Smith   PetscErrorCode         ierr;
1522*47c6ae99SBarry Smith   Vec                    xglobal,yglobal;
1523*47c6ae99SBarry Smith   PetscMPIInt            rank;
1524*47c6ae99SBarry Smith   DM_Composite           *comright;
1525*47c6ae99SBarry Smith   DM_Composite           *comleft;
1526*47c6ae99SBarry Smith 
1527*47c6ae99SBarry Smith   PetscFunctionBegin;
1528*47c6ae99SBarry Smith   ierr  = MatShellGetContext(A,(void**)&mpack);CHKERRQ(ierr);
1529*47c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)mpack->right)->comm,&rank);CHKERRQ(ierr);
1530*47c6ae99SBarry Smith   comright = (DM_Composite*)mpack->right->data;
1531*47c6ae99SBarry Smith   comleft = (DM_Composite*)mpack->left->data;
1532*47c6ae99SBarry Smith   ynext = comright->next;
1533*47c6ae99SBarry Smith   xnext = comleft->next;
1534*47c6ae99SBarry Smith   anext = mpack->next;
1535*47c6ae99SBarry Smith 
1536*47c6ae99SBarry Smith   while (xnext) {
1537*47c6ae99SBarry Smith     if (xnext->type == DMCOMPOSITE_ARRAY) {
1538*47c6ae99SBarry Smith       if (rank == ynext->rank) {
1539*47c6ae99SBarry Smith         ierr    = VecGetArray(x,&xarray);CHKERRQ(ierr);
1540*47c6ae99SBarry Smith         ierr    = VecGetArray(y,&yarray);CHKERRQ(ierr);
1541*47c6ae99SBarry Smith         ierr    = PetscMemcpy(yarray+ynext->rstart,xarray+xnext->rstart,xnext->n*sizeof(PetscScalar));CHKERRQ(ierr);
1542*47c6ae99SBarry Smith         ierr    = VecRestoreArray(x,&xarray);CHKERRQ(ierr);
1543*47c6ae99SBarry Smith         ierr    = VecRestoreArray(y,&yarray);CHKERRQ(ierr);
1544*47c6ae99SBarry Smith       }
1545*47c6ae99SBarry Smith     } else if (xnext->type == DMCOMPOSITE_DM) {
1546*47c6ae99SBarry Smith       ierr  = VecGetArray(x,&xarray);CHKERRQ(ierr);
1547*47c6ae99SBarry Smith       ierr  = VecGetArray(y,&yarray);CHKERRQ(ierr);
1548*47c6ae99SBarry Smith       ierr  = DMGetGlobalVector(xnext->dm,&xglobal);CHKERRQ(ierr);
1549*47c6ae99SBarry Smith       ierr  = DMGetGlobalVector(ynext->dm,&yglobal);CHKERRQ(ierr);
1550*47c6ae99SBarry Smith       ierr  = VecPlaceArray(xglobal,xarray+xnext->rstart);CHKERRQ(ierr);
1551*47c6ae99SBarry Smith       ierr  = VecPlaceArray(yglobal,yarray+ynext->rstart);CHKERRQ(ierr);
1552*47c6ae99SBarry Smith       ierr  = MatMultTranspose(anext->A,xglobal,yglobal);CHKERRQ(ierr);
1553*47c6ae99SBarry Smith       ierr  = VecRestoreArray(x,&xarray);CHKERRQ(ierr);
1554*47c6ae99SBarry Smith       ierr  = VecRestoreArray(y,&yarray);CHKERRQ(ierr);
1555*47c6ae99SBarry Smith       ierr  = VecResetArray(xglobal);CHKERRQ(ierr);
1556*47c6ae99SBarry Smith       ierr  = VecResetArray(yglobal);CHKERRQ(ierr);
1557*47c6ae99SBarry Smith       ierr  = DMRestoreGlobalVector(xnext->dm,&xglobal);CHKERRQ(ierr);
1558*47c6ae99SBarry Smith       ierr  = DMRestoreGlobalVector(ynext->dm,&yglobal);CHKERRQ(ierr);
1559*47c6ae99SBarry Smith       anext = anext->next;
1560*47c6ae99SBarry Smith     } else {
1561*47c6ae99SBarry Smith       SETERRQ(((PetscObject)A)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1562*47c6ae99SBarry Smith     }
1563*47c6ae99SBarry Smith     xnext = xnext->next;
1564*47c6ae99SBarry Smith     ynext = ynext->next;
1565*47c6ae99SBarry Smith   }
1566*47c6ae99SBarry Smith   PetscFunctionReturn(0);
1567*47c6ae99SBarry Smith }
1568*47c6ae99SBarry Smith 
1569*47c6ae99SBarry Smith #undef __FUNCT__
1570*47c6ae99SBarry Smith #define __FUNCT__ "MatDestroy_Shell_Pack"
1571*47c6ae99SBarry Smith PetscErrorCode MatDestroy_Shell_Pack(Mat A)
1572*47c6ae99SBarry Smith {
1573*47c6ae99SBarry Smith   struct MatPack     *mpack;
1574*47c6ae99SBarry Smith   struct MatPackLink *anext,*oldanext;
1575*47c6ae99SBarry Smith   PetscErrorCode     ierr;
1576*47c6ae99SBarry Smith 
1577*47c6ae99SBarry Smith   PetscFunctionBegin;
1578*47c6ae99SBarry Smith   ierr  = MatShellGetContext(A,(void**)&mpack);CHKERRQ(ierr);
1579*47c6ae99SBarry Smith   anext = mpack->next;
1580*47c6ae99SBarry Smith 
1581*47c6ae99SBarry Smith   while (anext) {
1582*47c6ae99SBarry Smith     ierr     = MatDestroy(anext->A);CHKERRQ(ierr);
1583*47c6ae99SBarry Smith     oldanext = anext;
1584*47c6ae99SBarry Smith     anext    = anext->next;
1585*47c6ae99SBarry Smith     ierr     = PetscFree(oldanext);CHKERRQ(ierr);
1586*47c6ae99SBarry Smith   }
1587*47c6ae99SBarry Smith   ierr = PetscFree(mpack);CHKERRQ(ierr);
1588*47c6ae99SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
1589*47c6ae99SBarry Smith   PetscFunctionReturn(0);
1590*47c6ae99SBarry Smith }
1591*47c6ae99SBarry Smith 
1592*47c6ae99SBarry Smith #undef __FUNCT__
1593*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetInterpolation"
1594*47c6ae99SBarry Smith /*@C
1595*47c6ae99SBarry Smith     DMCompositeGetInterpolation - GetInterpolations a DM by refining all of its DAs
1596*47c6ae99SBarry Smith 
1597*47c6ae99SBarry Smith     Collective on DMComposite
1598*47c6ae99SBarry Smith 
1599*47c6ae99SBarry Smith     Input Parameters:
1600*47c6ae99SBarry Smith +    coarse - coarse grid packer
1601*47c6ae99SBarry Smith -    fine - fine grid packer
1602*47c6ae99SBarry Smith 
1603*47c6ae99SBarry Smith     Output Parameter:
1604*47c6ae99SBarry Smith +    A - interpolation matrix
1605*47c6ae99SBarry Smith -    v - scaling vector
1606*47c6ae99SBarry Smith 
1607*47c6ae99SBarry Smith     Level: advanced
1608*47c6ae99SBarry Smith 
1609*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(),
1610*47c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(),
1611*47c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(),  DMCompositeScatter(),DMCompositeGetEntries()
1612*47c6ae99SBarry Smith 
1613*47c6ae99SBarry Smith @*/
1614*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGetInterpolation(DM coarse,DM fine,Mat *A,Vec *v)
1615*47c6ae99SBarry Smith {
1616*47c6ae99SBarry Smith   PetscErrorCode         ierr;
1617*47c6ae99SBarry Smith   PetscInt               m,n,M,N;
1618*47c6ae99SBarry Smith   struct DMCompositeLink *nextc;
1619*47c6ae99SBarry Smith   struct DMCompositeLink *nextf;
1620*47c6ae99SBarry Smith   struct MatPackLink     *nextmat,*pnextmat = 0;
1621*47c6ae99SBarry Smith   struct MatPack         *mpack;
1622*47c6ae99SBarry Smith   Vec                    gcoarse,gfine;
1623*47c6ae99SBarry Smith   DM_Composite           *comcoarse = (DM_Composite*)coarse->data;
1624*47c6ae99SBarry Smith   DM_Composite           *comfine = (DM_Composite*)fine->data;
1625*47c6ae99SBarry Smith 
1626*47c6ae99SBarry Smith   PetscFunctionBegin;
1627*47c6ae99SBarry Smith   PetscValidHeaderSpecific(coarse,DM_CLASSID,1);
1628*47c6ae99SBarry Smith   PetscValidHeaderSpecific(fine,DM_CLASSID,2);
1629*47c6ae99SBarry Smith   nextc = comcoarse->next;
1630*47c6ae99SBarry Smith   nextf = comfine->next;
1631*47c6ae99SBarry Smith   /* use global vectors only for determining matrix layout */
1632*47c6ae99SBarry Smith   ierr = DMCompositeCreateGlobalVector(coarse,&gcoarse);CHKERRQ(ierr);
1633*47c6ae99SBarry Smith   ierr = DMCompositeCreateGlobalVector(fine,&gfine);CHKERRQ(ierr);
1634*47c6ae99SBarry Smith   ierr = VecGetLocalSize(gcoarse,&n);CHKERRQ(ierr);
1635*47c6ae99SBarry Smith   ierr = VecGetLocalSize(gfine,&m);CHKERRQ(ierr);
1636*47c6ae99SBarry Smith   ierr = VecGetSize(gcoarse,&N);CHKERRQ(ierr);
1637*47c6ae99SBarry Smith   ierr = VecGetSize(gfine,&M);CHKERRQ(ierr);
1638*47c6ae99SBarry Smith   ierr = VecDestroy(gcoarse);CHKERRQ(ierr);
1639*47c6ae99SBarry Smith   ierr = VecDestroy(gfine);CHKERRQ(ierr);
1640*47c6ae99SBarry Smith 
1641*47c6ae99SBarry Smith   ierr         = PetscNew(struct MatPack,&mpack);CHKERRQ(ierr);
1642*47c6ae99SBarry Smith   mpack->right = coarse;
1643*47c6ae99SBarry Smith   mpack->left  = fine;
1644*47c6ae99SBarry Smith   ierr  = MatCreate(((PetscObject)fine)->comm,A);CHKERRQ(ierr);
1645*47c6ae99SBarry Smith   ierr  = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
1646*47c6ae99SBarry Smith   ierr  = MatSetType(*A,MATSHELL);CHKERRQ(ierr);
1647*47c6ae99SBarry Smith   ierr  = MatShellSetContext(*A,mpack);CHKERRQ(ierr);
1648*47c6ae99SBarry Smith   ierr  = MatShellSetOperation(*A,MATOP_MULT,(void(*)(void))MatMult_Shell_Pack);CHKERRQ(ierr);
1649*47c6ae99SBarry Smith   ierr  = MatShellSetOperation(*A,MATOP_MULT_TRANSPOSE,(void(*)(void))MatMultTranspose_Shell_Pack);CHKERRQ(ierr);
1650*47c6ae99SBarry Smith   ierr  = MatShellSetOperation(*A,MATOP_MULT_ADD,(void(*)(void))MatMultAdd_Shell_Pack);CHKERRQ(ierr);
1651*47c6ae99SBarry Smith   ierr  = MatShellSetOperation(*A,MATOP_DESTROY,(void(*)(void))MatDestroy_Shell_Pack);CHKERRQ(ierr);
1652*47c6ae99SBarry Smith 
1653*47c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
1654*47c6ae99SBarry Smith   while (nextc) {
1655*47c6ae99SBarry Smith     if (nextc->type != nextf->type) SETERRQ(((PetscObject)fine)->comm,PETSC_ERR_ARG_INCOMP,"Two DM have different layout");
1656*47c6ae99SBarry Smith 
1657*47c6ae99SBarry Smith     if (nextc->type == DMCOMPOSITE_ARRAY) {
1658*47c6ae99SBarry Smith       ;
1659*47c6ae99SBarry Smith     } else if (nextc->type == DMCOMPOSITE_DM) {
1660*47c6ae99SBarry Smith       ierr          = PetscNew(struct MatPackLink,&nextmat);CHKERRQ(ierr);
1661*47c6ae99SBarry Smith       nextmat->next = 0;
1662*47c6ae99SBarry Smith       if (pnextmat) {
1663*47c6ae99SBarry Smith         pnextmat->next = nextmat;
1664*47c6ae99SBarry Smith         pnextmat       = nextmat;
1665*47c6ae99SBarry Smith       } else {
1666*47c6ae99SBarry Smith         pnextmat    = nextmat;
1667*47c6ae99SBarry Smith         mpack->next = nextmat;
1668*47c6ae99SBarry Smith       }
1669*47c6ae99SBarry Smith       ierr = DMGetInterpolation(nextc->dm,nextf->dm,&nextmat->A,PETSC_NULL);CHKERRQ(ierr);
1670*47c6ae99SBarry Smith     } else {
1671*47c6ae99SBarry Smith       SETERRQ(((PetscObject)fine)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1672*47c6ae99SBarry Smith     }
1673*47c6ae99SBarry Smith     nextc = nextc->next;
1674*47c6ae99SBarry Smith     nextf = nextf->next;
1675*47c6ae99SBarry Smith   }
1676*47c6ae99SBarry Smith   PetscFunctionReturn(0);
1677*47c6ae99SBarry Smith }
1678*47c6ae99SBarry Smith 
1679*47c6ae99SBarry Smith #undef __FUNCT__
1680*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetMatrix"
1681*47c6ae99SBarry Smith /*@C
1682*47c6ae99SBarry Smith     DMCompositeGetMatrix - Creates a matrix with the correct parallel layout and nonzero structure required for
1683*47c6ae99SBarry Smith       computing the Jacobian on a function defined using the stencils set in the DA's and coupling in the array variables
1684*47c6ae99SBarry Smith 
1685*47c6ae99SBarry Smith     Collective on DA
1686*47c6ae99SBarry Smith 
1687*47c6ae99SBarry Smith     Input Parameter:
1688*47c6ae99SBarry Smith +   dm - the distributed array
1689*47c6ae99SBarry Smith -   mtype - Supported types are MATSEQAIJ, MATMPIAIJ
1690*47c6ae99SBarry Smith 
1691*47c6ae99SBarry Smith     Output Parameters:
1692*47c6ae99SBarry Smith .   J  - matrix with the correct nonzero structure
1693*47c6ae99SBarry Smith         (obviously without the correct Jacobian values)
1694*47c6ae99SBarry Smith 
1695*47c6ae99SBarry Smith     Level: advanced
1696*47c6ae99SBarry Smith 
1697*47c6ae99SBarry Smith     Notes: This properly preallocates the number of nonzeros in the sparse matrix so you
1698*47c6ae99SBarry Smith        do not need to do it yourself.
1699*47c6ae99SBarry Smith 
1700*47c6ae99SBarry Smith 
1701*47c6ae99SBarry Smith .seealso DAGetMatrix(), DMCompositeCreate()
1702*47c6ae99SBarry Smith 
1703*47c6ae99SBarry Smith @*/
1704*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGetMatrix(DM dm, const MatType mtype,Mat *J)
1705*47c6ae99SBarry Smith {
1706*47c6ae99SBarry Smith   PetscErrorCode         ierr;
1707*47c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
1708*47c6ae99SBarry Smith   struct DMCompositeLink *next = com->next;
1709*47c6ae99SBarry Smith   PetscInt               m,*dnz,*onz,i,j,mA;
1710*47c6ae99SBarry Smith   Mat                    Atmp;
1711*47c6ae99SBarry Smith   PetscMPIInt            rank;
1712*47c6ae99SBarry Smith   PetscScalar            zero = 0.0;
1713*47c6ae99SBarry Smith   PetscBool              dense = PETSC_FALSE;
1714*47c6ae99SBarry Smith 
1715*47c6ae99SBarry Smith   PetscFunctionBegin;
1716*47c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1717*47c6ae99SBarry Smith 
1718*47c6ae99SBarry Smith   /* use global vector to determine layout needed for matrix */
1719*47c6ae99SBarry Smith   m = com->n;
1720*47c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
1721*47c6ae99SBarry Smith   ierr = MatCreate(((PetscObject)dm)->comm,J);CHKERRQ(ierr);
1722*47c6ae99SBarry Smith   ierr = MatSetSizes(*J,m,m,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
1723*47c6ae99SBarry Smith   ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr);
1724*47c6ae99SBarry Smith 
1725*47c6ae99SBarry Smith   /*
1726*47c6ae99SBarry Smith      Extremely inefficient but will compute entire Jacobian for testing
1727*47c6ae99SBarry Smith   */
1728*47c6ae99SBarry Smith   ierr = PetscOptionsGetTruth(PETSC_NULL,"-dmcomposite_dense_jacobian",&dense,PETSC_NULL);CHKERRQ(ierr);
1729*47c6ae99SBarry Smith   if (dense) {
1730*47c6ae99SBarry Smith     PetscInt    rstart,rend,*indices;
1731*47c6ae99SBarry Smith     PetscScalar *values;
1732*47c6ae99SBarry Smith 
1733*47c6ae99SBarry Smith     mA    = com->N;
1734*47c6ae99SBarry Smith     ierr = MatMPIAIJSetPreallocation(*J,mA,PETSC_NULL,mA-m,PETSC_NULL);CHKERRQ(ierr);
1735*47c6ae99SBarry Smith     ierr = MatSeqAIJSetPreallocation(*J,mA,PETSC_NULL);CHKERRQ(ierr);
1736*47c6ae99SBarry Smith 
1737*47c6ae99SBarry Smith     ierr = MatGetOwnershipRange(*J,&rstart,&rend);CHKERRQ(ierr);
1738*47c6ae99SBarry Smith     ierr = PetscMalloc2(mA,PetscScalar,&values,mA,PetscInt,&indices);CHKERRQ(ierr);
1739*47c6ae99SBarry Smith     ierr = PetscMemzero(values,mA*sizeof(PetscScalar));CHKERRQ(ierr);
1740*47c6ae99SBarry Smith     for (i=0; i<mA; i++) indices[i] = i;
1741*47c6ae99SBarry Smith     for (i=rstart; i<rend; i++) {
1742*47c6ae99SBarry Smith       ierr = MatSetValues(*J,1,&i,mA,indices,values,INSERT_VALUES);CHKERRQ(ierr);
1743*47c6ae99SBarry Smith     }
1744*47c6ae99SBarry Smith     ierr = PetscFree2(values,indices);CHKERRQ(ierr);
1745*47c6ae99SBarry Smith     ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1746*47c6ae99SBarry Smith     ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1747*47c6ae99SBarry Smith     PetscFunctionReturn(0);
1748*47c6ae99SBarry Smith   }
1749*47c6ae99SBarry Smith 
1750*47c6ae99SBarry Smith   ierr = MatPreallocateInitialize(((PetscObject)dm)->comm,m,m,dnz,onz);CHKERRQ(ierr);
1751*47c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
1752*47c6ae99SBarry Smith   next = com->next;
1753*47c6ae99SBarry Smith   while (next) {
1754*47c6ae99SBarry Smith     if (next->type == DMCOMPOSITE_ARRAY) {
1755*47c6ae99SBarry Smith       if (rank == next->rank) {  /* zero the "little" block */
1756*47c6ae99SBarry Smith         for (j=com->rstart+next->rstart; j<com->rstart+next->rstart+next->n; j++) {
1757*47c6ae99SBarry Smith           for (i=com->rstart+next->rstart; i<com->rstart+next->rstart+next->n; i++) {
1758*47c6ae99SBarry Smith             ierr = MatPreallocateSet(j,1,&i,dnz,onz);CHKERRQ(ierr);
1759*47c6ae99SBarry Smith           }
1760*47c6ae99SBarry Smith         }
1761*47c6ae99SBarry Smith       }
1762*47c6ae99SBarry Smith     } else if (next->type == DMCOMPOSITE_DM) {
1763*47c6ae99SBarry Smith       PetscInt       nc,rstart,*ccols,maxnc;
1764*47c6ae99SBarry Smith       const PetscInt *cols,*rstarts;
1765*47c6ae99SBarry Smith       PetscMPIInt    proc;
1766*47c6ae99SBarry Smith 
1767*47c6ae99SBarry Smith       ierr = DMGetMatrix(next->dm,mtype,&Atmp);CHKERRQ(ierr);
1768*47c6ae99SBarry Smith       ierr = MatGetOwnershipRange(Atmp,&rstart,PETSC_NULL);CHKERRQ(ierr);
1769*47c6ae99SBarry Smith       ierr = MatGetOwnershipRanges(Atmp,&rstarts);CHKERRQ(ierr);
1770*47c6ae99SBarry Smith       ierr = MatGetLocalSize(Atmp,&mA,PETSC_NULL);CHKERRQ(ierr);
1771*47c6ae99SBarry Smith 
1772*47c6ae99SBarry Smith       maxnc = 0;
1773*47c6ae99SBarry Smith       for (i=0; i<mA; i++) {
1774*47c6ae99SBarry Smith         ierr  = MatGetRow(Atmp,rstart+i,&nc,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1775*47c6ae99SBarry Smith         ierr  = MatRestoreRow(Atmp,rstart+i,&nc,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1776*47c6ae99SBarry Smith         maxnc = PetscMax(nc,maxnc);
1777*47c6ae99SBarry Smith       }
1778*47c6ae99SBarry Smith       ierr = PetscMalloc(maxnc*sizeof(PetscInt),&ccols);CHKERRQ(ierr);
1779*47c6ae99SBarry Smith       for (i=0; i<mA; i++) {
1780*47c6ae99SBarry Smith         ierr = MatGetRow(Atmp,rstart+i,&nc,&cols,PETSC_NULL);CHKERRQ(ierr);
1781*47c6ae99SBarry Smith         /* remap the columns taking into how much they are shifted on each process */
1782*47c6ae99SBarry Smith         for (j=0; j<nc; j++) {
1783*47c6ae99SBarry Smith           proc = 0;
1784*47c6ae99SBarry Smith           while (cols[j] >= rstarts[proc+1]) proc++;
1785*47c6ae99SBarry Smith           ccols[j] = cols[j] + next->grstarts[proc] - rstarts[proc];
1786*47c6ae99SBarry Smith         }
1787*47c6ae99SBarry Smith         ierr = MatPreallocateSet(com->rstart+next->rstart+i,nc,ccols,dnz,onz);CHKERRQ(ierr);
1788*47c6ae99SBarry Smith         ierr = MatRestoreRow(Atmp,rstart+i,&nc,&cols,PETSC_NULL);CHKERRQ(ierr);
1789*47c6ae99SBarry Smith       }
1790*47c6ae99SBarry Smith       ierr = PetscFree(ccols);CHKERRQ(ierr);
1791*47c6ae99SBarry Smith       ierr = MatDestroy(Atmp);CHKERRQ(ierr);
1792*47c6ae99SBarry Smith     } else {
1793*47c6ae99SBarry Smith       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1794*47c6ae99SBarry Smith     }
1795*47c6ae99SBarry Smith     next = next->next;
1796*47c6ae99SBarry Smith   }
1797*47c6ae99SBarry Smith   if (com->FormCoupleLocations) {
1798*47c6ae99SBarry Smith     ierr = (*com->FormCoupleLocations)(dm,PETSC_NULL,dnz,onz,__rstart,__nrows,__start,__end);CHKERRQ(ierr);
1799*47c6ae99SBarry Smith   }
1800*47c6ae99SBarry Smith   ierr = MatMPIAIJSetPreallocation(*J,0,dnz,0,onz);CHKERRQ(ierr);
1801*47c6ae99SBarry Smith   ierr = MatSeqAIJSetPreallocation(*J,0,dnz);CHKERRQ(ierr);
1802*47c6ae99SBarry Smith   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
1803*47c6ae99SBarry Smith 
1804*47c6ae99SBarry Smith   next = com->next;
1805*47c6ae99SBarry Smith   while (next) {
1806*47c6ae99SBarry Smith     if (next->type == DMCOMPOSITE_ARRAY) {
1807*47c6ae99SBarry Smith       if (rank == next->rank) {
1808*47c6ae99SBarry Smith         for (j=com->rstart+next->rstart; j<com->rstart+next->rstart+next->n; j++) {
1809*47c6ae99SBarry Smith           for (i=com->rstart+next->rstart; i<com->rstart+next->rstart+next->n; i++) {
1810*47c6ae99SBarry Smith             ierr = MatSetValues(*J,1,&j,1,&i,&zero,INSERT_VALUES);CHKERRQ(ierr);
1811*47c6ae99SBarry Smith           }
1812*47c6ae99SBarry Smith         }
1813*47c6ae99SBarry Smith       }
1814*47c6ae99SBarry Smith     } else if (next->type == DMCOMPOSITE_DM) {
1815*47c6ae99SBarry Smith       PetscInt          nc,rstart,row,maxnc,*ccols;
1816*47c6ae99SBarry Smith       const PetscInt    *cols,*rstarts;
1817*47c6ae99SBarry Smith       const PetscScalar *values;
1818*47c6ae99SBarry Smith       PetscMPIInt       proc;
1819*47c6ae99SBarry Smith 
1820*47c6ae99SBarry Smith       ierr = DMGetMatrix(next->dm,mtype,&Atmp);CHKERRQ(ierr);
1821*47c6ae99SBarry Smith       ierr = MatGetOwnershipRange(Atmp,&rstart,PETSC_NULL);CHKERRQ(ierr);
1822*47c6ae99SBarry Smith       ierr = MatGetOwnershipRanges(Atmp,&rstarts);CHKERRQ(ierr);
1823*47c6ae99SBarry Smith       ierr = MatGetLocalSize(Atmp,&mA,PETSC_NULL);CHKERRQ(ierr);
1824*47c6ae99SBarry Smith       maxnc = 0;
1825*47c6ae99SBarry Smith       for (i=0; i<mA; i++) {
1826*47c6ae99SBarry Smith         ierr  = MatGetRow(Atmp,rstart+i,&nc,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1827*47c6ae99SBarry Smith         ierr  = MatRestoreRow(Atmp,rstart+i,&nc,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1828*47c6ae99SBarry Smith         maxnc = PetscMax(nc,maxnc);
1829*47c6ae99SBarry Smith       }
1830*47c6ae99SBarry Smith       ierr = PetscMalloc(maxnc*sizeof(PetscInt),&ccols);CHKERRQ(ierr);
1831*47c6ae99SBarry Smith       for (i=0; i<mA; i++) {
1832*47c6ae99SBarry Smith         ierr = MatGetRow(Atmp,rstart+i,&nc,(const PetscInt **)&cols,&values);CHKERRQ(ierr);
1833*47c6ae99SBarry Smith         for (j=0; j<nc; j++) {
1834*47c6ae99SBarry Smith           proc = 0;
1835*47c6ae99SBarry Smith           while (cols[j] >= rstarts[proc+1]) proc++;
1836*47c6ae99SBarry Smith           ccols[j] = cols[j] + next->grstarts[proc] - rstarts[proc];
1837*47c6ae99SBarry Smith         }
1838*47c6ae99SBarry Smith         row  = com->rstart+next->rstart+i;
1839*47c6ae99SBarry Smith         ierr = MatSetValues(*J,1,&row,nc,ccols,values,INSERT_VALUES);CHKERRQ(ierr);
1840*47c6ae99SBarry Smith         ierr = MatRestoreRow(Atmp,rstart+i,&nc,(const PetscInt **)&cols,&values);CHKERRQ(ierr);
1841*47c6ae99SBarry Smith       }
1842*47c6ae99SBarry Smith       ierr = PetscFree(ccols);CHKERRQ(ierr);
1843*47c6ae99SBarry Smith       ierr = MatDestroy(Atmp);CHKERRQ(ierr);
1844*47c6ae99SBarry Smith     } else {
1845*47c6ae99SBarry Smith       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1846*47c6ae99SBarry Smith     }
1847*47c6ae99SBarry Smith     next = next->next;
1848*47c6ae99SBarry Smith   }
1849*47c6ae99SBarry Smith   if (com->FormCoupleLocations) {
1850*47c6ae99SBarry Smith     PetscInt __rstart;
1851*47c6ae99SBarry Smith     ierr = MatGetOwnershipRange(*J,&__rstart,PETSC_NULL);CHKERRQ(ierr);
1852*47c6ae99SBarry Smith     ierr = (*com->FormCoupleLocations)(dm,*J,PETSC_NULL,PETSC_NULL,__rstart,0,0,0);CHKERRQ(ierr);
1853*47c6ae99SBarry Smith   }
1854*47c6ae99SBarry Smith   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1855*47c6ae99SBarry Smith   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1856*47c6ae99SBarry Smith   PetscFunctionReturn(0);
1857*47c6ae99SBarry Smith }
1858*47c6ae99SBarry Smith 
1859*47c6ae99SBarry Smith #undef __FUNCT__
1860*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetColoring"
1861*47c6ae99SBarry Smith /*@
1862*47c6ae99SBarry Smith     DMCompositeGetColoring - Gets the coloring required for computing the Jacobian via
1863*47c6ae99SBarry Smith     finite differences on a function defined using a DM "grid"
1864*47c6ae99SBarry Smith 
1865*47c6ae99SBarry Smith     Collective on DA
1866*47c6ae99SBarry Smith 
1867*47c6ae99SBarry Smith     Input Parameter:
1868*47c6ae99SBarry Smith +   dm - the DM object
1869*47c6ae99SBarry Smith .   ctype - IS_COLORING_GLOBAL or IS_COLORING_GHOSTED
1870*47c6ae99SBarry Smith -   mtype - MATAIJ or MATBAIJ
1871*47c6ae99SBarry Smith 
1872*47c6ae99SBarry Smith     Output Parameters:
1873*47c6ae99SBarry Smith .   coloring - matrix coloring for use in computing Jacobians (or PETSC_NULL if not needed)
1874*47c6ae99SBarry Smith 
1875*47c6ae99SBarry Smith     Level: advanced
1876*47c6ae99SBarry Smith 
1877*47c6ae99SBarry Smith     Notes: This colors each diagonal block (associated with a single DM) with a different set of colors;
1878*47c6ae99SBarry Smith       this it will compute the diagonal blocks of the Jacobian correctly. The off diagonal blocks are
1879*47c6ae99SBarry Smith       not computed, hence the Jacobian computed is not the entire Jacobian. If -dmcomposite_dense_jacobian
1880*47c6ae99SBarry Smith       is used then each column of the Jacobian is given a different color so the full Jacobian is computed
1881*47c6ae99SBarry Smith       correctly.
1882*47c6ae99SBarry Smith 
1883*47c6ae99SBarry Smith     Notes: These compute the graph coloring of the graph of A^{T}A. The coloring used
1884*47c6ae99SBarry Smith    for efficient (parallel or thread based) triangular solves etc is NOT yet
1885*47c6ae99SBarry Smith    available.
1886*47c6ae99SBarry Smith 
1887*47c6ae99SBarry Smith 
1888*47c6ae99SBarry Smith .seealso ISColoringView(), ISColoringGetIS(), MatFDColoringCreate(), ISColoringType, ISColoring, DAGetColoring()
1889*47c6ae99SBarry Smith 
1890*47c6ae99SBarry Smith @*/
1891*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGetColoring(DM dm,ISColoringType ctype,const MatType mtype,ISColoring *coloring)
1892*47c6ae99SBarry Smith {
1893*47c6ae99SBarry Smith   PetscErrorCode         ierr;
1894*47c6ae99SBarry Smith   PetscInt               n,i,cnt;
1895*47c6ae99SBarry Smith   ISColoringValue        *colors;
1896*47c6ae99SBarry Smith   PetscBool              dense = PETSC_FALSE;
1897*47c6ae99SBarry Smith   ISColoringValue        maxcol = 0;
1898*47c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
1899*47c6ae99SBarry Smith 
1900*47c6ae99SBarry Smith   PetscFunctionBegin;
1901*47c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1902*47c6ae99SBarry Smith   if (ctype == IS_COLORING_GHOSTED) {
1903*47c6ae99SBarry Smith     SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Currently you must use -dmmg_iscoloring_type global" );
1904*47c6ae99SBarry Smith   } else if (ctype == IS_COLORING_GLOBAL) {
1905*47c6ae99SBarry Smith     n = com->n;
1906*47c6ae99SBarry Smith   } else SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Unknown ISColoringType");
1907*47c6ae99SBarry Smith   ierr = PetscMalloc(n*sizeof(ISColoringValue),&colors);CHKERRQ(ierr); /* freed in ISColoringDestroy() */
1908*47c6ae99SBarry Smith 
1909*47c6ae99SBarry Smith   ierr = PetscOptionsGetTruth(PETSC_NULL,"-dmcomposite_dense_jacobian",&dense,PETSC_NULL);CHKERRQ(ierr);
1910*47c6ae99SBarry Smith   if (dense) {
1911*47c6ae99SBarry Smith     for (i=0; i<n; i++) {
1912*47c6ae99SBarry Smith       colors[i] = (ISColoringValue)(com->rstart + i);
1913*47c6ae99SBarry Smith     }
1914*47c6ae99SBarry Smith     maxcol = com->N;
1915*47c6ae99SBarry Smith   } else {
1916*47c6ae99SBarry Smith     struct DMCompositeLink *next = com->next;
1917*47c6ae99SBarry Smith     PetscMPIInt            rank;
1918*47c6ae99SBarry Smith 
1919*47c6ae99SBarry Smith     ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
1920*47c6ae99SBarry Smith     cnt  = 0;
1921*47c6ae99SBarry Smith     while (next) {
1922*47c6ae99SBarry Smith       if (next->type == DMCOMPOSITE_ARRAY) {
1923*47c6ae99SBarry Smith         if (rank == next->rank) {  /* each column gets is own color */
1924*47c6ae99SBarry Smith           for (i=com->rstart+next->rstart; i<com->rstart+next->rstart+next->n; i++) {
1925*47c6ae99SBarry Smith             colors[cnt++] = maxcol++;
1926*47c6ae99SBarry Smith           }
1927*47c6ae99SBarry Smith         }
1928*47c6ae99SBarry Smith         ierr = MPI_Bcast(&maxcol,1,MPIU_COLORING_VALUE,next->rank,((PetscObject)dm)->comm);CHKERRQ(ierr);
1929*47c6ae99SBarry Smith       } else if (next->type == DMCOMPOSITE_DM) {
1930*47c6ae99SBarry Smith         ISColoring     lcoloring;
1931*47c6ae99SBarry Smith 
1932*47c6ae99SBarry Smith         ierr = DMGetColoring(next->dm,IS_COLORING_GLOBAL,mtype,&lcoloring);CHKERRQ(ierr);
1933*47c6ae99SBarry Smith         for (i=0; i<lcoloring->N; i++) {
1934*47c6ae99SBarry Smith           colors[cnt++] = maxcol + lcoloring->colors[i];
1935*47c6ae99SBarry Smith         }
1936*47c6ae99SBarry Smith         maxcol += lcoloring->n;
1937*47c6ae99SBarry Smith         ierr = ISColoringDestroy(lcoloring);CHKERRQ(ierr);
1938*47c6ae99SBarry Smith       } else {
1939*47c6ae99SBarry Smith         SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
1940*47c6ae99SBarry Smith       }
1941*47c6ae99SBarry Smith       next = next->next;
1942*47c6ae99SBarry Smith     }
1943*47c6ae99SBarry Smith   }
1944*47c6ae99SBarry Smith   ierr = ISColoringCreate(((PetscObject)dm)->comm,maxcol,n,colors,coloring);CHKERRQ(ierr);
1945*47c6ae99SBarry Smith   PetscFunctionReturn(0);
1946*47c6ae99SBarry Smith }
1947*47c6ae99SBarry Smith 
1948*47c6ae99SBarry Smith #undef __FUNCT__
1949*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGlobalToLocalBegin"
1950*47c6ae99SBarry Smith /*@C
1951*47c6ae99SBarry Smith     DMCompositeGlobalToLocalBegin - begin update of single local vector from global vector
1952*47c6ae99SBarry Smith 
1953*47c6ae99SBarry Smith     Neighbor-wise Collective on DMComposite
1954*47c6ae99SBarry Smith 
1955*47c6ae99SBarry Smith     Input Parameter:
1956*47c6ae99SBarry Smith +    dm - the packer object
1957*47c6ae99SBarry Smith .    gvec - the global vector
1958*47c6ae99SBarry Smith -    lvec - single local vector
1959*47c6ae99SBarry Smith 
1960*47c6ae99SBarry Smith     Level: advanced
1961*47c6ae99SBarry Smith 
1962*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(),
1963*47c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(),
1964*47c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
1965*47c6ae99SBarry Smith 
1966*47c6ae99SBarry Smith @*/
1967*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGlobalToLocalBegin(DM dm,Vec gvec,InsertMode mode,Vec lvec)
1968*47c6ae99SBarry Smith {
1969*47c6ae99SBarry Smith   PetscErrorCode         ierr;
1970*47c6ae99SBarry Smith   struct DMCompositeLink *next;
1971*47c6ae99SBarry Smith   PetscInt               cnt = 3;
1972*47c6ae99SBarry Smith   PetscMPIInt            rank;
1973*47c6ae99SBarry Smith   PetscScalar            *garray,*larray;
1974*47c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
1975*47c6ae99SBarry Smith 
1976*47c6ae99SBarry Smith   PetscFunctionBegin;
1977*47c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1978*47c6ae99SBarry Smith   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
1979*47c6ae99SBarry Smith   next = com->next;
1980*47c6ae99SBarry Smith   if (!com->setup) {
1981*47c6ae99SBarry Smith     ierr = DMCompositeSetUp(dm);CHKERRQ(ierr);
1982*47c6ae99SBarry Smith   }
1983*47c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
1984*47c6ae99SBarry Smith   ierr = VecGetArray(gvec,&garray);CHKERRQ(ierr);
1985*47c6ae99SBarry Smith   ierr = VecGetArray(lvec,&larray);CHKERRQ(ierr);
1986*47c6ae99SBarry Smith 
1987*47c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
1988*47c6ae99SBarry Smith   while (next) {
1989*47c6ae99SBarry Smith     if (next->type == DMCOMPOSITE_ARRAY) {
1990*47c6ae99SBarry Smith       if (rank == next->rank) {
1991*47c6ae99SBarry Smith         ierr    = PetscMemcpy(larray,garray,next->n*sizeof(PetscScalar));CHKERRQ(ierr);
1992*47c6ae99SBarry Smith         garray += next->n;
1993*47c6ae99SBarry Smith       }
1994*47c6ae99SBarry Smith       /* does not handle ADD_VALUES */
1995*47c6ae99SBarry Smith       ierr = MPI_Bcast(larray,next->n,MPIU_SCALAR,next->rank,((PetscObject)dm)->comm);CHKERRQ(ierr);
1996*47c6ae99SBarry Smith       larray += next->n;
1997*47c6ae99SBarry Smith     } else if (next->type == DMCOMPOSITE_DM) {
1998*47c6ae99SBarry Smith       Vec      local,global;
1999*47c6ae99SBarry Smith       PetscInt N;
2000*47c6ae99SBarry Smith 
2001*47c6ae99SBarry Smith       ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
2002*47c6ae99SBarry Smith       ierr = VecGetLocalSize(global,&N);CHKERRQ(ierr);
2003*47c6ae99SBarry Smith       ierr = VecPlaceArray(global,garray);CHKERRQ(ierr);
2004*47c6ae99SBarry Smith       ierr = DMGetLocalVector(next->dm,&local);CHKERRQ(ierr);
2005*47c6ae99SBarry Smith       ierr = VecPlaceArray(local,larray);CHKERRQ(ierr);
2006*47c6ae99SBarry Smith       ierr = DMGlobalToLocalBegin(next->dm,global,mode,local);CHKERRQ(ierr);
2007*47c6ae99SBarry Smith       ierr = DMGlobalToLocalEnd(next->dm,global,mode,local);CHKERRQ(ierr);
2008*47c6ae99SBarry Smith       ierr = VecResetArray(global);CHKERRQ(ierr);
2009*47c6ae99SBarry Smith       ierr = VecResetArray(local);CHKERRQ(ierr);
2010*47c6ae99SBarry Smith       ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
2011*47c6ae99SBarry Smith       ierr = DMRestoreGlobalVector(next->dm,&local);CHKERRQ(ierr);
2012*47c6ae99SBarry Smith       larray += next->n;
2013*47c6ae99SBarry Smith     } else {
2014*47c6ae99SBarry Smith       SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet");
2015*47c6ae99SBarry Smith     }
2016*47c6ae99SBarry Smith     cnt++;
2017*47c6ae99SBarry Smith     next = next->next;
2018*47c6ae99SBarry Smith   }
2019*47c6ae99SBarry Smith 
2020*47c6ae99SBarry Smith   ierr = VecRestoreArray(gvec,PETSC_NULL);CHKERRQ(ierr);
2021*47c6ae99SBarry Smith   ierr = VecRestoreArray(lvec,PETSC_NULL);CHKERRQ(ierr);
2022*47c6ae99SBarry Smith   PetscFunctionReturn(0);
2023*47c6ae99SBarry Smith }
2024*47c6ae99SBarry Smith 
2025*47c6ae99SBarry Smith #undef __FUNCT__
2026*47c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGlobalToLocalEnd"
2027*47c6ae99SBarry Smith /*@C
2028*47c6ae99SBarry Smith     DMCompositeGlobalToLocalEnd - All communication is handled in the Begin phase
2029*47c6ae99SBarry Smith 
2030*47c6ae99SBarry Smith     Neighbor-wise Collective on DMComposite
2031*47c6ae99SBarry Smith 
2032*47c6ae99SBarry Smith     Input Parameter:
2033*47c6ae99SBarry Smith +    dm - the packer object
2034*47c6ae99SBarry Smith .    gvec - the global vector
2035*47c6ae99SBarry Smith -    lvec - single local vector
2036*47c6ae99SBarry Smith 
2037*47c6ae99SBarry Smith     Level: advanced
2038*47c6ae99SBarry Smith 
2039*47c6ae99SBarry Smith .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(),
2040*47c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(),
2041*47c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
2042*47c6ae99SBarry Smith 
2043*47c6ae99SBarry Smith @*/
2044*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGlobalToLocalEnd(DM dm,Vec gvec,InsertMode mode,Vec lvec)
2045*47c6ae99SBarry Smith {
2046*47c6ae99SBarry Smith   PetscFunctionBegin;
2047*47c6ae99SBarry Smith   PetscFunctionReturn(0);
2048*47c6ae99SBarry Smith }
2049