xref: /petsc/src/dm/impls/composite/pack.c (revision 73e31fe287e90bf7d8f915b02b2c934a4e6aaee4)
147c6ae99SBarry Smith 
2ccd284c7SBarry Smith #include <../src/dm/impls/composite/packimpl.h>       /*I  "petscdmcomposite.h"  I*/
347c6ae99SBarry Smith 
447c6ae99SBarry Smith #undef __FUNCT__
547c6ae99SBarry Smith #define __FUNCT__ "DMCompositeSetCoupling"
647c6ae99SBarry Smith /*@C
747c6ae99SBarry Smith     DMCompositeSetCoupling - Sets user provided routines that compute the coupling between the
89ae5db72SJed Brown       seperate components (DMs) in a DMto build the correct matrix nonzero structure.
947c6ae99SBarry Smith 
1047c6ae99SBarry Smith 
1147c6ae99SBarry Smith     Logically Collective on MPI_Comm
1247c6ae99SBarry Smith 
1347c6ae99SBarry Smith     Input Parameter:
1447c6ae99SBarry Smith +   dm - the composite object
1547c6ae99SBarry Smith -   formcouplelocations - routine to set the nonzero locations in the matrix
1647c6ae99SBarry Smith 
1747c6ae99SBarry Smith     Level: advanced
1847c6ae99SBarry Smith 
191b2093e4SBarry Smith     Notes: See DMSetApplicationContext() and DMGetApplicationContext() for how to get user information into
2047c6ae99SBarry Smith         this routine
2147c6ae99SBarry Smith 
2247c6ae99SBarry Smith @*/
237087cfbeSBarry Smith PetscErrorCode  DMCompositeSetCoupling(DM dm,PetscErrorCode (*FormCoupleLocations)(DM,Mat,PetscInt*,PetscInt*,PetscInt,PetscInt,PetscInt,PetscInt))
2447c6ae99SBarry Smith {
2547c6ae99SBarry Smith   DM_Composite *com = (DM_Composite*)dm->data;
2647c6ae99SBarry Smith 
2747c6ae99SBarry Smith   PetscFunctionBegin;
2847c6ae99SBarry Smith   com->FormCoupleLocations = FormCoupleLocations;
2947c6ae99SBarry Smith   PetscFunctionReturn(0);
3047c6ae99SBarry Smith }
3147c6ae99SBarry Smith 
3247c6ae99SBarry Smith #undef __FUNCT__
330c010503SBarry Smith #define __FUNCT__ "DMDestroy_Composite"
346bf464f9SBarry Smith PetscErrorCode  DMDestroy_Composite(DM dm)
3547c6ae99SBarry Smith {
3647c6ae99SBarry Smith   PetscErrorCode         ierr;
3747c6ae99SBarry Smith   struct DMCompositeLink *next, *prev;
3847c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
3947c6ae99SBarry Smith 
4047c6ae99SBarry Smith   PetscFunctionBegin;
4147c6ae99SBarry Smith   next = com->next;
4247c6ae99SBarry Smith   while (next) {
4347c6ae99SBarry Smith     prev = next;
4447c6ae99SBarry Smith     next = next->next;
45fcfd50ebSBarry Smith     ierr = DMDestroy(&prev->dm);CHKERRQ(ierr);
4647c6ae99SBarry Smith     ierr = PetscFree(prev->grstarts);CHKERRQ(ierr);
4747c6ae99SBarry Smith     ierr = PetscFree(prev);CHKERRQ(ierr);
4847c6ae99SBarry Smith   }
49435a35e8SMatthew G Knepley   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
50435a35e8SMatthew G Knepley   ierr = PetscFree(com);CHKERRQ(ierr);
5147c6ae99SBarry Smith   PetscFunctionReturn(0);
5247c6ae99SBarry Smith }
5347c6ae99SBarry Smith 
5447c6ae99SBarry Smith #undef __FUNCT__
550c010503SBarry Smith #define __FUNCT__ "DMView_Composite"
567087cfbeSBarry Smith PetscErrorCode  DMView_Composite(DM dm,PetscViewer v)
5747c6ae99SBarry Smith {
5847c6ae99SBarry Smith   PetscErrorCode ierr;
5947c6ae99SBarry Smith   PetscBool      iascii;
6047c6ae99SBarry Smith   DM_Composite   *com = (DM_Composite*)dm->data;
6147c6ae99SBarry Smith 
6247c6ae99SBarry Smith   PetscFunctionBegin;
63251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
6447c6ae99SBarry Smith   if (iascii) {
6547c6ae99SBarry Smith     struct DMCompositeLink *lnk = com->next;
6647c6ae99SBarry Smith     PetscInt               i;
6747c6ae99SBarry Smith 
6847c6ae99SBarry Smith     ierr = PetscViewerASCIIPrintf(v,"DM (%s)\n",((PetscObject)dm)->prefix ? ((PetscObject)dm)->prefix : "no prefix");CHKERRQ(ierr);
699ae5db72SJed Brown     ierr = PetscViewerASCIIPrintf(v,"  contains %D DMs\n",com->nDM);CHKERRQ(ierr);
7047c6ae99SBarry Smith     ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr);
7147c6ae99SBarry Smith     for (i=0; lnk; lnk=lnk->next,i++) {
729ae5db72SJed Brown       ierr = PetscViewerASCIIPrintf(v,"Link %D: DM of type %s\n",i,((PetscObject)lnk->dm)->type_name);CHKERRQ(ierr);
7347c6ae99SBarry Smith       ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr);
7447c6ae99SBarry Smith       ierr = DMView(lnk->dm,v);CHKERRQ(ierr);
7547c6ae99SBarry Smith       ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr);
7647c6ae99SBarry Smith     }
7747c6ae99SBarry Smith     ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr);
7847c6ae99SBarry Smith   }
7947c6ae99SBarry Smith   PetscFunctionReturn(0);
8047c6ae99SBarry Smith }
8147c6ae99SBarry Smith 
8247c6ae99SBarry Smith /* --------------------------------------------------------------------------------------*/
8347c6ae99SBarry Smith #undef __FUNCT__
84d7bf68aeSBarry Smith #define __FUNCT__ "DMSetUp_Composite"
857087cfbeSBarry Smith PetscErrorCode  DMSetUp_Composite(DM dm)
8647c6ae99SBarry Smith {
8747c6ae99SBarry Smith   PetscErrorCode         ierr;
8847c6ae99SBarry Smith   PetscInt               nprev = 0;
8947c6ae99SBarry Smith   PetscMPIInt            rank,size;
9047c6ae99SBarry Smith   DM_Composite           *com  = (DM_Composite*)dm->data;
9147c6ae99SBarry Smith   struct DMCompositeLink *next = com->next;
9247c6ae99SBarry Smith   PetscLayout            map;
9347c6ae99SBarry Smith 
9447c6ae99SBarry Smith   PetscFunctionBegin;
9547c6ae99SBarry Smith   if (com->setup) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"Packer has already been setup");
9647c6ae99SBarry Smith   ierr = PetscLayoutCreate(((PetscObject)dm)->comm,&map);CHKERRQ(ierr);
9747c6ae99SBarry Smith   ierr = PetscLayoutSetLocalSize(map,com->n);CHKERRQ(ierr);
9847c6ae99SBarry Smith   ierr = PetscLayoutSetSize(map,PETSC_DETERMINE);CHKERRQ(ierr);
9947c6ae99SBarry Smith   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
10047c6ae99SBarry Smith   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
10147c6ae99SBarry Smith   ierr = PetscLayoutGetSize(map,&com->N);CHKERRQ(ierr);
10247c6ae99SBarry Smith   ierr = PetscLayoutGetRange(map,&com->rstart,PETSC_NULL);CHKERRQ(ierr);
103fcfd50ebSBarry Smith   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
10447c6ae99SBarry Smith 
1059ae5db72SJed Brown   /* now set the rstart for each linked vector */
10647c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
10747c6ae99SBarry Smith   ierr = MPI_Comm_size(((PetscObject)dm)->comm,&size);CHKERRQ(ierr);
10847c6ae99SBarry Smith   while (next) {
10947c6ae99SBarry Smith     next->rstart  = nprev;
11006ebdd98SJed Brown     nprev        += next->n;
11147c6ae99SBarry Smith     next->grstart = com->rstart + next->rstart;
11247c6ae99SBarry Smith     ierr          = PetscMalloc(size*sizeof(PetscInt),&next->grstarts);CHKERRQ(ierr);
11347c6ae99SBarry Smith     ierr          = MPI_Allgather(&next->grstart,1,MPIU_INT,next->grstarts,1,MPIU_INT,((PetscObject)dm)->comm);CHKERRQ(ierr);
11447c6ae99SBarry Smith     next          = next->next;
11547c6ae99SBarry Smith   }
11647c6ae99SBarry Smith   com->setup = PETSC_TRUE;
11747c6ae99SBarry Smith   PetscFunctionReturn(0);
11847c6ae99SBarry Smith }
11947c6ae99SBarry Smith 
12047c6ae99SBarry Smith /* ----------------------------------------------------------------------------------*/
12147c6ae99SBarry Smith 
12247c6ae99SBarry Smith #include <stdarg.h>
12347c6ae99SBarry Smith 
12447c6ae99SBarry Smith #undef __FUNCT__
12547c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetNumberDM"
126*73e31fe2SJed Brown /*@
12747c6ae99SBarry Smith     DMCompositeGetNumberDM - Get's the number of DM objects in the DMComposite
12847c6ae99SBarry Smith        representation.
12947c6ae99SBarry Smith 
13047c6ae99SBarry Smith     Not Collective
13147c6ae99SBarry Smith 
13247c6ae99SBarry Smith     Input Parameter:
13347c6ae99SBarry Smith .    dm - the packer object
13447c6ae99SBarry Smith 
13547c6ae99SBarry Smith     Output Parameter:
13647c6ae99SBarry Smith .     nDM - the number of DMs
13747c6ae99SBarry Smith 
13847c6ae99SBarry Smith     Level: beginner
13947c6ae99SBarry Smith 
14047c6ae99SBarry Smith @*/
1417087cfbeSBarry Smith PetscErrorCode  DMCompositeGetNumberDM(DM dm,PetscInt *nDM)
14247c6ae99SBarry Smith {
14347c6ae99SBarry Smith   DM_Composite *com = (DM_Composite*)dm->data;
1445fd66863SKarl Rupp 
14547c6ae99SBarry Smith   PetscFunctionBegin;
14647c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
14747c6ae99SBarry Smith   *nDM = com->nDM;
14847c6ae99SBarry Smith   PetscFunctionReturn(0);
14947c6ae99SBarry Smith }
15047c6ae99SBarry Smith 
15147c6ae99SBarry Smith 
15247c6ae99SBarry Smith #undef __FUNCT__
15347c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetAccess"
15447c6ae99SBarry Smith /*@C
15547c6ae99SBarry Smith     DMCompositeGetAccess - Allows one to access the individual packed vectors in their global
15647c6ae99SBarry Smith        representation.
15747c6ae99SBarry Smith 
15847c6ae99SBarry Smith     Collective on DMComposite
15947c6ae99SBarry Smith 
1609ae5db72SJed Brown     Input Parameters:
16147c6ae99SBarry Smith +    dm - the packer object
1629ae5db72SJed Brown -    gvec - the global vector
1639ae5db72SJed Brown 
1649ae5db72SJed Brown     Output Parameters:
1659ae5db72SJed Brown .    Vec* ... - the packed parallel vectors, PETSC_NULL for those that are not needed
16647c6ae99SBarry Smith 
16747c6ae99SBarry Smith     Notes: Use DMCompositeRestoreAccess() to return the vectors when you no longer need them
16847c6ae99SBarry Smith 
16947c6ae99SBarry Smith     Level: advanced
17047c6ae99SBarry Smith 
17147c6ae99SBarry Smith @*/
1727087cfbeSBarry Smith PetscErrorCode  DMCompositeGetAccess(DM dm,Vec gvec,...)
17347c6ae99SBarry Smith {
17447c6ae99SBarry Smith   va_list                Argp;
17547c6ae99SBarry Smith   PetscErrorCode         ierr;
17647c6ae99SBarry Smith   struct DMCompositeLink *next;
17747c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
17847c6ae99SBarry Smith 
17947c6ae99SBarry Smith   PetscFunctionBegin;
18047c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
18147c6ae99SBarry Smith   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
18247c6ae99SBarry Smith   next = com->next;
18347c6ae99SBarry Smith   if (!com->setup) {
184d7bf68aeSBarry Smith     ierr = DMSetUp(dm);CHKERRQ(ierr);
18547c6ae99SBarry Smith   }
18647c6ae99SBarry Smith 
18747c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
18847c6ae99SBarry Smith   va_start(Argp,gvec);
18947c6ae99SBarry Smith   while (next) {
19047c6ae99SBarry Smith     Vec *vec;
19147c6ae99SBarry Smith     vec = va_arg(Argp, Vec*);
1929ae5db72SJed Brown     if (vec) {
1939ae5db72SJed Brown       PetscScalar *array;
1949ae5db72SJed Brown       ierr = DMGetGlobalVector(next->dm,vec);CHKERRQ(ierr);
1959ae5db72SJed Brown       ierr = VecGetArray(gvec,&array);CHKERRQ(ierr);
1969ae5db72SJed Brown       ierr = VecPlaceArray(*vec,array+next->rstart);CHKERRQ(ierr);
1979ae5db72SJed Brown       ierr = VecRestoreArray(gvec,&array);CHKERRQ(ierr);
19847c6ae99SBarry Smith     }
19947c6ae99SBarry Smith     next = next->next;
20047c6ae99SBarry Smith   }
20147c6ae99SBarry Smith   va_end(Argp);
20247c6ae99SBarry Smith   PetscFunctionReturn(0);
20347c6ae99SBarry Smith }
20447c6ae99SBarry Smith 
20547c6ae99SBarry Smith #undef __FUNCT__
20647c6ae99SBarry Smith #define __FUNCT__ "DMCompositeRestoreAccess"
20747c6ae99SBarry Smith /*@C
208aa219208SBarry Smith     DMCompositeRestoreAccess - Returns the vectors obtained with DMCompositeGetAccess()
20947c6ae99SBarry Smith        representation.
21047c6ae99SBarry Smith 
21147c6ae99SBarry Smith     Collective on DMComposite
21247c6ae99SBarry Smith 
2139ae5db72SJed Brown     Input Parameters:
21447c6ae99SBarry Smith +    dm - the packer object
21547c6ae99SBarry Smith .    gvec - the global vector
2169ae5db72SJed Brown -    Vec* ... - the individual parallel vectors, PETSC_NULL for those that are not needed
21747c6ae99SBarry Smith 
21847c6ae99SBarry Smith     Level: advanced
21947c6ae99SBarry Smith 
2209ae5db72SJed Brown .seealso  DMCompositeAddDM(), DMCreateGlobalVector(),
2216eb61c8cSJed Brown          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeScatter(),
222aa219208SBarry Smith          DMCompositeRestoreAccess(), DMCompositeGetAccess()
22347c6ae99SBarry Smith 
22447c6ae99SBarry Smith @*/
2257087cfbeSBarry Smith PetscErrorCode  DMCompositeRestoreAccess(DM dm,Vec gvec,...)
22647c6ae99SBarry Smith {
22747c6ae99SBarry Smith   va_list                Argp;
22847c6ae99SBarry Smith   PetscErrorCode         ierr;
22947c6ae99SBarry Smith   struct DMCompositeLink *next;
23047c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
23147c6ae99SBarry Smith 
23247c6ae99SBarry Smith   PetscFunctionBegin;
23347c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
23447c6ae99SBarry Smith   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
23547c6ae99SBarry Smith   next = com->next;
23647c6ae99SBarry Smith   if (!com->setup) {
237d7bf68aeSBarry Smith     ierr = DMSetUp(dm);CHKERRQ(ierr);
23847c6ae99SBarry Smith   }
23947c6ae99SBarry Smith 
24047c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
24147c6ae99SBarry Smith   va_start(Argp,gvec);
24247c6ae99SBarry Smith   while (next) {
24347c6ae99SBarry Smith     Vec *vec;
24447c6ae99SBarry Smith     vec = va_arg(Argp, Vec*);
2459ae5db72SJed Brown     if (vec) {
2469ae5db72SJed Brown       ierr = VecResetArray(*vec);CHKERRQ(ierr);
2479ae5db72SJed Brown       ierr = DMRestoreGlobalVector(next->dm,vec);CHKERRQ(ierr);
24847c6ae99SBarry Smith     }
24947c6ae99SBarry Smith     next = next->next;
25047c6ae99SBarry Smith   }
25147c6ae99SBarry Smith   va_end(Argp);
25247c6ae99SBarry Smith   PetscFunctionReturn(0);
25347c6ae99SBarry Smith }
25447c6ae99SBarry Smith 
25547c6ae99SBarry Smith #undef __FUNCT__
25647c6ae99SBarry Smith #define __FUNCT__ "DMCompositeScatter"
25747c6ae99SBarry Smith /*@C
25847c6ae99SBarry Smith     DMCompositeScatter - Scatters from a global packed vector into its individual local vectors
25947c6ae99SBarry Smith 
26047c6ae99SBarry Smith     Collective on DMComposite
26147c6ae99SBarry Smith 
2629ae5db72SJed Brown     Input Parameters:
26347c6ae99SBarry Smith +    dm - the packer object
26447c6ae99SBarry Smith .    gvec - the global vector
2659ae5db72SJed Brown -    Vec ... - the individual sequential vectors, PETSC_NULL for those that are not needed
26647c6ae99SBarry Smith 
26747c6ae99SBarry Smith     Level: advanced
26847c6ae99SBarry Smith 
2699ae5db72SJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
2706eb61c8cSJed Brown          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
27147c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
27247c6ae99SBarry Smith 
27347c6ae99SBarry Smith @*/
2747087cfbeSBarry Smith PetscErrorCode  DMCompositeScatter(DM dm,Vec gvec,...)
27547c6ae99SBarry Smith {
27647c6ae99SBarry Smith   va_list                Argp;
27747c6ae99SBarry Smith   PetscErrorCode         ierr;
27847c6ae99SBarry Smith   struct DMCompositeLink *next;
2798fd8f222SJed Brown   PetscInt               cnt;
28047c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
28147c6ae99SBarry Smith 
28247c6ae99SBarry Smith   PetscFunctionBegin;
28347c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
28447c6ae99SBarry Smith   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
28547c6ae99SBarry Smith   if (!com->setup) {
286d7bf68aeSBarry Smith     ierr = DMSetUp(dm);CHKERRQ(ierr);
28747c6ae99SBarry Smith   }
28847c6ae99SBarry Smith 
28947c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
29047c6ae99SBarry Smith   va_start(Argp,gvec);
2918fd8f222SJed Brown   for (cnt=3,next=com->next; next; cnt++,next=next->next) {
2929ae5db72SJed Brown     Vec local;
2939ae5db72SJed Brown     local = va_arg(Argp, Vec);
2949ae5db72SJed Brown     if (local) {
2959ae5db72SJed Brown       Vec         global;
29647c6ae99SBarry Smith       PetscScalar *array;
2979ae5db72SJed Brown       PetscValidHeaderSpecific(local,VEC_CLASSID,cnt);
2989ae5db72SJed Brown       ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
2999ae5db72SJed Brown       ierr = VecGetArray(gvec,&array);CHKERRQ(ierr);
3009ae5db72SJed Brown       ierr = VecPlaceArray(global,array+next->rstart);CHKERRQ(ierr);
3019ae5db72SJed Brown       ierr = DMGlobalToLocalBegin(next->dm,global,INSERT_VALUES,local);CHKERRQ(ierr);
3029ae5db72SJed Brown       ierr = DMGlobalToLocalEnd(next->dm,global,INSERT_VALUES,local);CHKERRQ(ierr);
3039ae5db72SJed Brown       ierr = VecRestoreArray(gvec,&array);CHKERRQ(ierr);
3049ae5db72SJed Brown       ierr = VecResetArray(global);CHKERRQ(ierr);
3059ae5db72SJed Brown       ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
30647c6ae99SBarry Smith     }
30747c6ae99SBarry Smith   }
30847c6ae99SBarry Smith   va_end(Argp);
30947c6ae99SBarry Smith   PetscFunctionReturn(0);
31047c6ae99SBarry Smith }
31147c6ae99SBarry Smith 
31247c6ae99SBarry Smith #undef __FUNCT__
31347c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGather"
31447c6ae99SBarry Smith /*@C
31547c6ae99SBarry Smith     DMCompositeGather - Gathers into a global packed vector from its individual local vectors
31647c6ae99SBarry Smith 
31747c6ae99SBarry Smith     Collective on DMComposite
31847c6ae99SBarry Smith 
31947c6ae99SBarry Smith     Input Parameter:
32047c6ae99SBarry Smith +    dm - the packer object
32147c6ae99SBarry Smith .    gvec - the global vector
3229ae5db72SJed Brown -    Vec ... - the individual sequential vectors, PETSC_NULL for any that are not needed
32347c6ae99SBarry Smith 
32447c6ae99SBarry Smith     Level: advanced
32547c6ae99SBarry Smith 
3269ae5db72SJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
3276eb61c8cSJed Brown          DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
32847c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
32947c6ae99SBarry Smith 
33047c6ae99SBarry Smith @*/
3317087cfbeSBarry Smith PetscErrorCode  DMCompositeGather(DM dm,Vec gvec,InsertMode imode,...)
33247c6ae99SBarry Smith {
33347c6ae99SBarry Smith   va_list                Argp;
33447c6ae99SBarry Smith   PetscErrorCode         ierr;
33547c6ae99SBarry Smith   struct DMCompositeLink *next;
33647c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
3378fd8f222SJed Brown   PetscInt               cnt;
33847c6ae99SBarry Smith 
33947c6ae99SBarry Smith   PetscFunctionBegin;
34047c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
34147c6ae99SBarry Smith   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
34247c6ae99SBarry Smith   if (!com->setup) {
343d7bf68aeSBarry Smith     ierr = DMSetUp(dm);CHKERRQ(ierr);
34447c6ae99SBarry Smith   }
34547c6ae99SBarry Smith 
34647c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
347df0c820aSJed Brown   va_start(Argp,imode);
3488fd8f222SJed Brown   for (cnt=3,next=com->next; next; cnt++,next=next->next) {
3499ae5db72SJed Brown     Vec local;
3509ae5db72SJed Brown     local = va_arg(Argp, Vec);
3519ae5db72SJed Brown     if (local) {
35247c6ae99SBarry Smith       PetscScalar *array;
3539ae5db72SJed Brown       Vec         global;
3549ae5db72SJed Brown       PetscValidHeaderSpecific(local,VEC_CLASSID,cnt);
3559ae5db72SJed Brown       ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
3569ae5db72SJed Brown       ierr = VecGetArray(gvec,&array);CHKERRQ(ierr);
3579ae5db72SJed Brown       ierr = VecPlaceArray(global,array+next->rstart);CHKERRQ(ierr);
3589ae5db72SJed Brown       ierr = DMLocalToGlobalBegin(next->dm,local,imode,global);CHKERRQ(ierr);
3599ae5db72SJed Brown       ierr = DMLocalToGlobalEnd(next->dm,local,imode,global);CHKERRQ(ierr);
3609ae5db72SJed Brown       ierr = VecRestoreArray(gvec,&array);CHKERRQ(ierr);
3619ae5db72SJed Brown       ierr = VecResetArray(global);CHKERRQ(ierr);
3629ae5db72SJed Brown       ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
36347c6ae99SBarry Smith     }
36447c6ae99SBarry Smith   }
36547c6ae99SBarry Smith   va_end(Argp);
36647c6ae99SBarry Smith   PetscFunctionReturn(0);
36747c6ae99SBarry Smith }
36847c6ae99SBarry Smith 
36947c6ae99SBarry Smith #undef __FUNCT__
37047c6ae99SBarry Smith #define __FUNCT__ "DMCompositeAddDM"
37147c6ae99SBarry Smith /*@C
372aa219208SBarry Smith     DMCompositeAddDM - adds a DM  vector to a DMComposite
37347c6ae99SBarry Smith 
37447c6ae99SBarry Smith     Collective on DMComposite
37547c6ae99SBarry Smith 
37647c6ae99SBarry Smith     Input Parameter:
37747c6ae99SBarry Smith +    dm - the packer object
37847c6ae99SBarry Smith -    dm - the DM object, if the DM is a da you will need to caste it with a (DM)
37947c6ae99SBarry Smith 
38047c6ae99SBarry Smith     Level: advanced
38147c6ae99SBarry Smith 
3820c010503SBarry Smith .seealso DMDestroy(), DMCompositeGather(), DMCompositeAddDM(), DMCreateGlobalVector(),
3836eb61c8cSJed Brown          DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
38447c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
38547c6ae99SBarry Smith 
38647c6ae99SBarry Smith @*/
3877087cfbeSBarry Smith PetscErrorCode  DMCompositeAddDM(DM dmc,DM dm)
38847c6ae99SBarry Smith {
38947c6ae99SBarry Smith   PetscErrorCode         ierr;
39006ebdd98SJed Brown   PetscInt               n,nlocal;
39147c6ae99SBarry Smith   struct DMCompositeLink *mine,*next;
39206ebdd98SJed Brown   Vec                    global,local;
39347c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dmc->data;
39447c6ae99SBarry Smith 
39547c6ae99SBarry Smith   PetscFunctionBegin;
39647c6ae99SBarry Smith   PetscValidHeaderSpecific(dmc,DM_CLASSID,1);
39747c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,2);
39847c6ae99SBarry Smith   next = com->next;
399aa219208SBarry Smith   if (com->setup) SETERRQ(((PetscObject)dmc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Cannot add a DM once you have used the DMComposite");
40047c6ae99SBarry Smith 
40147c6ae99SBarry Smith   /* create new link */
40247c6ae99SBarry Smith   ierr = PetscNew(struct DMCompositeLink,&mine);CHKERRQ(ierr);
40347c6ae99SBarry Smith   ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
40447c6ae99SBarry Smith   ierr = DMGetGlobalVector(dm,&global);CHKERRQ(ierr);
40547c6ae99SBarry Smith   ierr = VecGetLocalSize(global,&n);CHKERRQ(ierr);
40647c6ae99SBarry Smith   ierr = DMRestoreGlobalVector(dm,&global);CHKERRQ(ierr);
40706ebdd98SJed Brown   ierr = DMGetLocalVector(dm,&local);CHKERRQ(ierr);
40806ebdd98SJed Brown   ierr = VecGetSize(local,&nlocal);CHKERRQ(ierr);
40906ebdd98SJed Brown   ierr = DMRestoreLocalVector(dm,&local);CHKERRQ(ierr);
4108865f1eaSKarl Rupp 
41147c6ae99SBarry Smith   mine->n      = n;
41206ebdd98SJed Brown   mine->nlocal = nlocal;
41347c6ae99SBarry Smith   mine->dm     = dm;
41447c6ae99SBarry Smith   mine->next   = PETSC_NULL;
41547c6ae99SBarry Smith   com->n      += n;
41647c6ae99SBarry Smith 
41747c6ae99SBarry Smith   /* add to end of list */
4188865f1eaSKarl Rupp   if (!next) com->next = mine;
4198865f1eaSKarl Rupp   else {
42047c6ae99SBarry Smith     while (next->next) next = next->next;
42147c6ae99SBarry Smith     next->next = mine;
42247c6ae99SBarry Smith   }
42347c6ae99SBarry Smith   com->nDM++;
42447c6ae99SBarry Smith   com->nmine++;
42547c6ae99SBarry Smith   PetscFunctionReturn(0);
42647c6ae99SBarry Smith }
42747c6ae99SBarry Smith 
4287087cfbeSBarry Smith extern PetscErrorCode  VecView_MPI(Vec,PetscViewer);
42947c6ae99SBarry Smith EXTERN_C_BEGIN
43047c6ae99SBarry Smith #undef __FUNCT__
43147c6ae99SBarry Smith #define __FUNCT__ "VecView_DMComposite"
4327087cfbeSBarry Smith PetscErrorCode  VecView_DMComposite(Vec gvec,PetscViewer viewer)
43347c6ae99SBarry Smith {
43447c6ae99SBarry Smith   DM                     dm;
43547c6ae99SBarry Smith   PetscErrorCode         ierr;
43647c6ae99SBarry Smith   struct DMCompositeLink *next;
43747c6ae99SBarry Smith   PetscBool              isdraw;
438cef07954SSatish Balay   DM_Composite           *com;
43947c6ae99SBarry Smith 
44047c6ae99SBarry Smith   PetscFunctionBegin;
441c688c046SMatthew G Knepley   ierr = VecGetDM(gvec, &dm);CHKERRQ(ierr);
44247c6ae99SBarry Smith   if (!dm) SETERRQ(((PetscObject)gvec)->comm,PETSC_ERR_ARG_WRONG,"Vector not generated from a DMComposite");
44347c6ae99SBarry Smith   com  = (DM_Composite*)dm->data;
44447c6ae99SBarry Smith   next = com->next;
44547c6ae99SBarry Smith 
446251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
44747c6ae99SBarry Smith   if (!isdraw) {
44847c6ae99SBarry Smith     /* do I really want to call this? */
44947c6ae99SBarry Smith     ierr = VecView_MPI(gvec,viewer);CHKERRQ(ierr);
45047c6ae99SBarry Smith   } else {
45147c6ae99SBarry Smith     PetscInt cnt = 0;
45247c6ae99SBarry Smith 
45347c6ae99SBarry Smith     /* loop over packed objects, handling one at at time */
45447c6ae99SBarry Smith     while (next) {
45547c6ae99SBarry Smith       Vec         vec;
4569ae5db72SJed Brown       PetscScalar *array;
45747c6ae99SBarry Smith       PetscInt    bs;
45847c6ae99SBarry Smith 
4599ae5db72SJed Brown       /* Should use VecGetSubVector() eventually, but would need to forward the DM for that to work */
4609ae5db72SJed Brown       ierr = DMGetGlobalVector(next->dm,&vec);CHKERRQ(ierr);
4619ae5db72SJed Brown       ierr = VecGetArray(gvec,&array);CHKERRQ(ierr);
4629ae5db72SJed Brown       ierr = VecPlaceArray(vec,array+next->rstart);CHKERRQ(ierr);
4639ae5db72SJed Brown       ierr = VecRestoreArray(gvec,&array);CHKERRQ(ierr);
46447c6ae99SBarry Smith       ierr = VecView(vec,viewer);CHKERRQ(ierr);
46547c6ae99SBarry Smith       ierr = VecGetBlockSize(vec,&bs);CHKERRQ(ierr);
4669ae5db72SJed Brown       ierr = VecResetArray(vec);CHKERRQ(ierr);
4679ae5db72SJed Brown       ierr = DMRestoreGlobalVector(next->dm,&vec);CHKERRQ(ierr);
46847c6ae99SBarry Smith       ierr = PetscViewerDrawBaseAdd(viewer,bs);CHKERRQ(ierr);
46947c6ae99SBarry Smith       cnt += bs;
47047c6ae99SBarry Smith       next = next->next;
47147c6ae99SBarry Smith     }
47247c6ae99SBarry Smith     ierr = PetscViewerDrawBaseAdd(viewer,-cnt);CHKERRQ(ierr);
47347c6ae99SBarry Smith   }
47447c6ae99SBarry Smith   PetscFunctionReturn(0);
47547c6ae99SBarry Smith }
47647c6ae99SBarry Smith EXTERN_C_END
47747c6ae99SBarry Smith 
47847c6ae99SBarry Smith 
47947c6ae99SBarry Smith #undef __FUNCT__
4800c010503SBarry Smith #define __FUNCT__ "DMCreateGlobalVector_Composite"
4817087cfbeSBarry Smith PetscErrorCode  DMCreateGlobalVector_Composite(DM dm,Vec *gvec)
48247c6ae99SBarry Smith {
48347c6ae99SBarry Smith   PetscErrorCode ierr;
48447c6ae99SBarry Smith   DM_Composite   *com = (DM_Composite*)dm->data;
48547c6ae99SBarry Smith 
48647c6ae99SBarry Smith   PetscFunctionBegin;
48747c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
488d7bf68aeSBarry Smith   ierr = DMSetUp(dm);CHKERRQ(ierr);
48947c6ae99SBarry Smith   ierr = VecCreateMPI(((PetscObject)dm)->comm,com->n,com->N,gvec);CHKERRQ(ierr);
490c688c046SMatthew G Knepley   ierr = VecSetDM(*gvec, dm);CHKERRQ(ierr);
49147c6ae99SBarry Smith   ierr = VecSetOperation(*gvec,VECOP_VIEW,(void (*)(void))VecView_DMComposite);CHKERRQ(ierr);
49247c6ae99SBarry Smith   PetscFunctionReturn(0);
49347c6ae99SBarry Smith }
49447c6ae99SBarry Smith 
49547c6ae99SBarry Smith #undef __FUNCT__
4960c010503SBarry Smith #define __FUNCT__ "DMCreateLocalVector_Composite"
4977087cfbeSBarry Smith PetscErrorCode  DMCreateLocalVector_Composite(DM dm,Vec *lvec)
49847c6ae99SBarry Smith {
49947c6ae99SBarry Smith   PetscErrorCode ierr;
50047c6ae99SBarry Smith   DM_Composite   *com = (DM_Composite*)dm->data;
50147c6ae99SBarry Smith 
50247c6ae99SBarry Smith   PetscFunctionBegin;
50347c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
50447c6ae99SBarry Smith   if (!com->setup) {
505d7bf68aeSBarry Smith     ierr = DMSetUp(dm);CHKERRQ(ierr);
50647c6ae99SBarry Smith   }
50747c6ae99SBarry Smith   ierr = VecCreateSeq(((PetscObject)dm)->comm,com->nghost,lvec);CHKERRQ(ierr);
508c688c046SMatthew G Knepley   ierr = VecSetDM(*lvec, dm);CHKERRQ(ierr);
50947c6ae99SBarry Smith   PetscFunctionReturn(0);
51047c6ae99SBarry Smith }
51147c6ae99SBarry Smith 
51247c6ae99SBarry Smith #undef __FUNCT__
5136eb61c8cSJed Brown #define __FUNCT__ "DMCompositeGetISLocalToGlobalMappings"
51447c6ae99SBarry Smith /*@C
5159ae5db72SJed Brown     DMCompositeGetISLocalToGlobalMappings - gets an ISLocalToGlobalMapping for each DM in the DMComposite, maps to the composite global space
51647c6ae99SBarry Smith 
51706ebdd98SJed Brown     Collective on DM
51847c6ae99SBarry Smith 
51947c6ae99SBarry Smith     Input Parameter:
52047c6ae99SBarry Smith .    dm - the packer object
52147c6ae99SBarry Smith 
52247c6ae99SBarry Smith     Output Parameters:
5239ae5db72SJed Brown .    ltogs - the individual mappings for each packed vector. Note that this includes
5249ae5db72SJed Brown            all the ghost points that individual ghosted DMDA's may have.
52547c6ae99SBarry Smith 
52647c6ae99SBarry Smith     Level: advanced
52747c6ae99SBarry Smith 
52847c6ae99SBarry Smith     Notes:
5296eb61c8cSJed Brown        Each entry of ltogs should be destroyed with ISLocalToGlobalMappingDestroy(), the ltogs array should be freed with PetscFree().
53047c6ae99SBarry Smith 
5319ae5db72SJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
53247c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetAccess(), DMCompositeScatter(),
53347c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(),DMCompositeGetEntries()
53447c6ae99SBarry Smith 
53547c6ae99SBarry Smith @*/
5367087cfbeSBarry Smith PetscErrorCode  DMCompositeGetISLocalToGlobalMappings(DM dm,ISLocalToGlobalMapping **ltogs)
53747c6ae99SBarry Smith {
53847c6ae99SBarry Smith   PetscErrorCode         ierr;
53947c6ae99SBarry Smith   PetscInt               i,*idx,n,cnt;
54047c6ae99SBarry Smith   struct DMCompositeLink *next;
54147c6ae99SBarry Smith   PetscMPIInt            rank;
54247c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
54347c6ae99SBarry Smith 
54447c6ae99SBarry Smith   PetscFunctionBegin;
54547c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
546728e99d6SJed Brown   ierr = DMSetUp(dm);CHKERRQ(ierr);
5479ae5db72SJed Brown   ierr = PetscMalloc((com->nDM)*sizeof(ISLocalToGlobalMapping),ltogs);CHKERRQ(ierr);
54847c6ae99SBarry Smith   next = com->next;
54947c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
55047c6ae99SBarry Smith 
55147c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
55247c6ae99SBarry Smith   cnt = 0;
55347c6ae99SBarry Smith   while (next) {
5546eb61c8cSJed Brown     ISLocalToGlobalMapping ltog;
5556eb61c8cSJed Brown     PetscMPIInt            size;
55686994e45SJed Brown     const PetscInt         *suboff,*indices;
5576eb61c8cSJed Brown     Vec                    global;
55847c6ae99SBarry Smith 
5596eb61c8cSJed Brown     /* Get sub-DM global indices for each local dof */
5601411c6eeSJed Brown     ierr = DMGetLocalToGlobalMapping(next->dm,&ltog);CHKERRQ(ierr);
5616eb61c8cSJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltog,&n);CHKERRQ(ierr);
56286994e45SJed Brown     ierr = ISLocalToGlobalMappingGetIndices(ltog,&indices);CHKERRQ(ierr);
56347c6ae99SBarry Smith     ierr = PetscMalloc(n*sizeof(PetscInt),&idx);CHKERRQ(ierr);
56447c6ae99SBarry Smith 
5656eb61c8cSJed Brown     /* Get the offsets for the sub-DM global vector */
5666eb61c8cSJed Brown     ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
5676eb61c8cSJed Brown     ierr = VecGetOwnershipRanges(global,&suboff);CHKERRQ(ierr);
5686eb61c8cSJed Brown     ierr = MPI_Comm_size(((PetscObject)global)->comm,&size);CHKERRQ(ierr);
5696eb61c8cSJed Brown 
5706eb61c8cSJed Brown     /* Shift the sub-DM definition of the global space to the composite global space */
5716eb61c8cSJed Brown     for (i=0; i<n; i++) {
57286994e45SJed Brown       PetscInt subi = indices[i],lo = 0,hi = size,t;
5736eb61c8cSJed Brown       /* Binary search to find which rank owns subi */
5746eb61c8cSJed Brown       while (hi-lo > 1) {
5756eb61c8cSJed Brown         t = lo + (hi-lo)/2;
5766eb61c8cSJed Brown         if (suboff[t] > subi) hi = t;
5776eb61c8cSJed Brown         else                  lo = t;
5786eb61c8cSJed Brown       }
5796eb61c8cSJed Brown       idx[i] = subi - suboff[lo] + next->grstarts[lo];
5806eb61c8cSJed Brown     }
58186994e45SJed Brown     ierr = ISLocalToGlobalMappingRestoreIndices(ltog,&indices);CHKERRQ(ierr);
5826eb61c8cSJed Brown     ierr = ISLocalToGlobalMappingCreate(((PetscObject)dm)->comm,n,idx,PETSC_OWN_POINTER,&(*ltogs)[cnt]);CHKERRQ(ierr);
5836eb61c8cSJed Brown     ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
58447c6ae99SBarry Smith     next = next->next;
58547c6ae99SBarry Smith     cnt++;
58647c6ae99SBarry Smith   }
58747c6ae99SBarry Smith   PetscFunctionReturn(0);
58847c6ae99SBarry Smith }
58947c6ae99SBarry Smith 
59047c6ae99SBarry Smith #undef __FUNCT__
59187c85e80SJed Brown #define __FUNCT__ "DMCompositeGetLocalISs"
59287c85e80SJed Brown /*@C
5939ae5db72SJed Brown    DMCompositeGetLocalISs - Gets index sets for each component of a composite local vector
59487c85e80SJed Brown 
59587c85e80SJed Brown    Not Collective
59687c85e80SJed Brown 
59787c85e80SJed Brown    Input Arguments:
59887c85e80SJed Brown . dm - composite DM
59987c85e80SJed Brown 
60087c85e80SJed Brown    Output Arguments:
60187c85e80SJed Brown . is - array of serial index sets for each each component of the DMComposite
60287c85e80SJed Brown 
60387c85e80SJed Brown    Level: intermediate
60487c85e80SJed Brown 
60587c85e80SJed Brown    Notes:
60687c85e80SJed Brown    At present, a composite local vector does not normally exist.  This function is used to provide index sets for
60787c85e80SJed Brown    MatGetLocalSubMatrix().  In the future, the scatters for each entry in the DMComposite may be be merged into a single
6089ae5db72SJed Brown    scatter to a composite local vector.  The user should not typically need to know which is being done.
60987c85e80SJed Brown 
61087c85e80SJed Brown    To get the composite global indices at all local points (including ghosts), use DMCompositeGetISLocalToGlobalMappings().
61187c85e80SJed Brown 
61287c85e80SJed Brown    To get index sets for pieces of the composite global vector, use DMCompositeGetGlobalISs().
61387c85e80SJed Brown 
61487c85e80SJed Brown    Each returned IS should be destroyed with ISDestroy(), the array should be freed with PetscFree().
61587c85e80SJed Brown 
61687c85e80SJed Brown .seealso: DMCompositeGetGlobalISs(), DMCompositeGetISLocalToGlobalMappings(), MatGetLocalSubMatrix(), MatCreateLocalRef()
61787c85e80SJed Brown @*/
6187087cfbeSBarry Smith PetscErrorCode  DMCompositeGetLocalISs(DM dm,IS **is)
61987c85e80SJed Brown {
62087c85e80SJed Brown   PetscErrorCode         ierr;
62187c85e80SJed Brown   DM_Composite           *com = (DM_Composite*)dm->data;
62287c85e80SJed Brown   struct DMCompositeLink *link;
62387c85e80SJed Brown   PetscInt               cnt,start;
62487c85e80SJed Brown 
62587c85e80SJed Brown   PetscFunctionBegin;
62687c85e80SJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
62787c85e80SJed Brown   PetscValidPointer(is,2);
62887c85e80SJed Brown   ierr = PetscMalloc(com->nmine*sizeof(IS),is);CHKERRQ(ierr);
62906ebdd98SJed Brown   for (cnt=0,start=0,link=com->next; link; start+=link->nlocal,cnt++,link=link->next) {
630520db06cSJed Brown     PetscInt bs;
6319ae5db72SJed Brown     ierr = ISCreateStride(PETSC_COMM_SELF,link->nlocal,start,1,&(*is)[cnt]);CHKERRQ(ierr);
6321411c6eeSJed Brown     ierr = DMGetBlockSize(link->dm,&bs);CHKERRQ(ierr);
633520db06cSJed Brown     ierr = ISSetBlockSize((*is)[cnt],bs);CHKERRQ(ierr);
634520db06cSJed Brown   }
63587c85e80SJed Brown   PetscFunctionReturn(0);
63687c85e80SJed Brown }
63787c85e80SJed Brown 
63887c85e80SJed Brown #undef __FUNCT__
63947c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetGlobalISs"
64047c6ae99SBarry Smith /*@C
64147c6ae99SBarry Smith     DMCompositeGetGlobalISs - Gets the index sets for each composed object
64247c6ae99SBarry Smith 
64347c6ae99SBarry Smith     Collective on DMComposite
64447c6ae99SBarry Smith 
64547c6ae99SBarry Smith     Input Parameter:
64647c6ae99SBarry Smith .    dm - the packer object
64747c6ae99SBarry Smith 
64847c6ae99SBarry Smith     Output Parameters:
64947c6ae99SBarry Smith .    is - the array of index sets
65047c6ae99SBarry Smith 
65147c6ae99SBarry Smith     Level: advanced
65247c6ae99SBarry Smith 
65347c6ae99SBarry Smith     Notes:
65447c6ae99SBarry Smith        The is entries should be destroyed with ISDestroy(), the is array should be freed with PetscFree()
65547c6ae99SBarry Smith 
65647c6ae99SBarry Smith        These could be used to extract a subset of vector entries for a "multi-physics" preconditioner
65747c6ae99SBarry Smith 
6586eb61c8cSJed Brown        Use DMCompositeGetLocalISs() for index sets in the packed local numbering, and
6596eb61c8cSJed Brown        DMCompositeGetISLocalToGlobalMappings() for to map local sub-DM (including ghost) indices to packed global
6606eb61c8cSJed Brown        indices.
66147c6ae99SBarry Smith 
6629ae5db72SJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
66347c6ae99SBarry Smith          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetAccess(), DMCompositeScatter(),
66447c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(),DMCompositeGetEntries()
66547c6ae99SBarry Smith 
66647c6ae99SBarry Smith @*/
6676eb61c8cSJed Brown 
6687087cfbeSBarry Smith PetscErrorCode  DMCompositeGetGlobalISs(DM dm,IS *is[])
66947c6ae99SBarry Smith {
67047c6ae99SBarry Smith   PetscErrorCode         ierr;
67147c6ae99SBarry Smith   PetscInt               cnt = 0,*idx,i;
67247c6ae99SBarry Smith   struct DMCompositeLink *next;
67347c6ae99SBarry Smith   PetscMPIInt            rank;
67447c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
67547c6ae99SBarry Smith 
67647c6ae99SBarry Smith   PetscFunctionBegin;
67747c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
6789ae5db72SJed Brown   ierr = PetscMalloc((com->nDM)*sizeof(IS),is);CHKERRQ(ierr);
67947c6ae99SBarry Smith   next = com->next;
68047c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
68147c6ae99SBarry Smith 
68247c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
68347c6ae99SBarry Smith   while (next) {
68447c6ae99SBarry Smith     ierr = PetscMalloc(next->n*sizeof(PetscInt),&idx);CHKERRQ(ierr);
68547c6ae99SBarry Smith     for (i=0; i<next->n; i++) idx[i] = next->grstart + i;
68647c6ae99SBarry Smith     ierr = ISCreateGeneral(((PetscObject)dm)->comm,next->n,idx,PETSC_OWN_POINTER,&(*is)[cnt]);CHKERRQ(ierr);
68747c6ae99SBarry Smith     cnt++;
68847c6ae99SBarry Smith     next = next->next;
68947c6ae99SBarry Smith   }
69047c6ae99SBarry Smith   PetscFunctionReturn(0);
69147c6ae99SBarry Smith }
69247c6ae99SBarry Smith 
6934d343eeaSMatthew G Knepley #undef __FUNCT__
6944d343eeaSMatthew G Knepley #define __FUNCT__ "DMCreateFieldIS_Composite"
69521c9b008SJed Brown PetscErrorCode DMCreateFieldIS_Composite(DM dm, PetscInt *numFields,char ***fieldNames, IS **fields)
6964d343eeaSMatthew G Knepley {
6974d343eeaSMatthew G Knepley   PetscInt       nDM;
6984d343eeaSMatthew G Knepley   DM             *dms;
6994d343eeaSMatthew G Knepley   PetscInt       i;
7004d343eeaSMatthew G Knepley   PetscErrorCode ierr;
7014d343eeaSMatthew G Knepley 
7024d343eeaSMatthew G Knepley   PetscFunctionBegin;
7034d343eeaSMatthew G Knepley   ierr = DMCompositeGetNumberDM(dm, &nDM);CHKERRQ(ierr);
7048865f1eaSKarl Rupp   if (numFields) *numFields = nDM;
7054d343eeaSMatthew G Knepley   ierr = DMCompositeGetGlobalISs(dm, fields);CHKERRQ(ierr);
7064d343eeaSMatthew G Knepley   if (fieldNames) {
7074d343eeaSMatthew G Knepley     ierr = PetscMalloc(nDM*sizeof(DM), &dms);CHKERRQ(ierr);
7084d343eeaSMatthew G Knepley     ierr = PetscMalloc(nDM*sizeof(const char*), fieldNames);CHKERRQ(ierr);
7094d343eeaSMatthew G Knepley     ierr = DMCompositeGetEntriesArray(dm, dms);CHKERRQ(ierr);
7104d343eeaSMatthew G Knepley     for (i=0; i<nDM; i++) {
7114d343eeaSMatthew G Knepley       char       buf[256];
7124d343eeaSMatthew G Knepley       const char *splitname;
7134d343eeaSMatthew G Knepley 
7144d343eeaSMatthew G Knepley       /* Split naming precedence: object name, prefix, number */
7154d343eeaSMatthew G Knepley       splitname = ((PetscObject) dm)->name;
7164d343eeaSMatthew G Knepley       if (!splitname) {
7174d343eeaSMatthew G Knepley         ierr = PetscObjectGetOptionsPrefix((PetscObject)dms[i],&splitname);CHKERRQ(ierr);
7184d343eeaSMatthew G Knepley         if (splitname) {
7194d343eeaSMatthew G Knepley           size_t len;
7208caf3d72SBarry Smith           ierr                 = PetscStrncpy(buf,splitname,sizeof(buf));CHKERRQ(ierr);
7218caf3d72SBarry Smith           buf[sizeof(buf) - 1] = 0;
7224d343eeaSMatthew G Knepley           ierr                 = PetscStrlen(buf,&len);CHKERRQ(ierr);
7234d343eeaSMatthew G Knepley           if (buf[len-1] == '_') buf[len-1] = 0; /* Remove trailing underscore if it was used */
7244d343eeaSMatthew G Knepley           splitname = buf;
7254d343eeaSMatthew G Knepley         }
7264d343eeaSMatthew G Knepley       }
7274d343eeaSMatthew G Knepley       if (!splitname) {
7288caf3d72SBarry Smith         ierr      = PetscSNPrintf(buf,sizeof(buf),"%D",i);CHKERRQ(ierr);
7294d343eeaSMatthew G Knepley         splitname = buf;
7304d343eeaSMatthew G Knepley       }
73121c9b008SJed Brown       ierr = PetscStrallocpy(splitname,&(*fieldNames)[i]);CHKERRQ(ierr);
7324d343eeaSMatthew G Knepley     }
7334d343eeaSMatthew G Knepley     ierr = PetscFree(dms);CHKERRQ(ierr);
7344d343eeaSMatthew G Knepley   }
7354d343eeaSMatthew G Knepley   PetscFunctionReturn(0);
7364d343eeaSMatthew G Knepley }
7374d343eeaSMatthew G Knepley 
738e7c4fc90SDmitry Karpeev /*
739e7c4fc90SDmitry Karpeev  This could take over from DMCreateFieldIS(), as it is more general,
740e7c4fc90SDmitry Karpeev  making DMCreateFieldIS() a special case -- calling with dmlist == PETSC_NULL;
741e7c4fc90SDmitry Karpeev  At this point it's probably best to be less intrusive, however.
742e7c4fc90SDmitry Karpeev  */
743e7c4fc90SDmitry Karpeev #undef __FUNCT__
74416621825SDmitry Karpeev #define __FUNCT__ "DMCreateFieldDecomposition_Composite"
74516621825SDmitry Karpeev PetscErrorCode DMCreateFieldDecomposition_Composite(DM dm, PetscInt *len,char ***namelist, IS **islist, DM **dmlist)
746e7c4fc90SDmitry Karpeev {
747e7c4fc90SDmitry Karpeev   PetscInt       nDM;
748e7c4fc90SDmitry Karpeev   PetscInt       i;
749e7c4fc90SDmitry Karpeev   PetscErrorCode ierr;
750e7c4fc90SDmitry Karpeev 
751e7c4fc90SDmitry Karpeev   PetscFunctionBegin;
752e7c4fc90SDmitry Karpeev   ierr = DMCreateFieldIS_Composite(dm, len, namelist, islist);CHKERRQ(ierr);
753e7c4fc90SDmitry Karpeev   if (dmlist) {
754e7c4fc90SDmitry Karpeev     ierr = DMCompositeGetNumberDM(dm, &nDM);CHKERRQ(ierr);
755e7c4fc90SDmitry Karpeev     ierr = PetscMalloc(nDM*sizeof(DM), dmlist);CHKERRQ(ierr);
756e7c4fc90SDmitry Karpeev     ierr = DMCompositeGetEntriesArray(dm, *dmlist);CHKERRQ(ierr);
757e7c4fc90SDmitry Karpeev     for (i=0; i<nDM; i++) {
758e7c4fc90SDmitry Karpeev       ierr = PetscObjectReference((PetscObject)((*dmlist)[i]));CHKERRQ(ierr);
759e7c4fc90SDmitry Karpeev     }
760e7c4fc90SDmitry Karpeev   }
761e7c4fc90SDmitry Karpeev   PetscFunctionReturn(0);
762e7c4fc90SDmitry Karpeev }
763e7c4fc90SDmitry Karpeev 
764e7c4fc90SDmitry Karpeev 
765e7c4fc90SDmitry Karpeev 
76647c6ae99SBarry Smith /* -------------------------------------------------------------------------------------*/
76747c6ae99SBarry Smith #undef __FUNCT__
76847c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetLocalVectors"
76947c6ae99SBarry Smith /*@C
7709ae5db72SJed Brown     DMCompositeGetLocalVectors - Gets local vectors for each part of a DMComposite.
77147c6ae99SBarry Smith        Use DMCompositeRestoreLocalVectors() to return them.
77247c6ae99SBarry Smith 
77347c6ae99SBarry Smith     Not Collective
77447c6ae99SBarry Smith 
77547c6ae99SBarry Smith     Input Parameter:
77647c6ae99SBarry Smith .    dm - the packer object
77747c6ae99SBarry Smith 
77847c6ae99SBarry Smith     Output Parameter:
7799ae5db72SJed Brown .   Vec ... - the individual sequential Vecs
78047c6ae99SBarry Smith 
78147c6ae99SBarry Smith     Level: advanced
78247c6ae99SBarry Smith 
7839ae5db72SJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
7846eb61c8cSJed Brown          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
78547c6ae99SBarry Smith          DMCompositeRestoreLocalVectors(), DMCompositeScatter(), DMCompositeGetEntries()
78647c6ae99SBarry Smith 
78747c6ae99SBarry Smith @*/
7887087cfbeSBarry Smith PetscErrorCode  DMCompositeGetLocalVectors(DM dm,...)
78947c6ae99SBarry Smith {
79047c6ae99SBarry Smith   va_list                Argp;
79147c6ae99SBarry Smith   PetscErrorCode         ierr;
79247c6ae99SBarry Smith   struct DMCompositeLink *next;
79347c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
79447c6ae99SBarry Smith 
79547c6ae99SBarry Smith   PetscFunctionBegin;
79647c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
79747c6ae99SBarry Smith   next = com->next;
79847c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
79947c6ae99SBarry Smith   va_start(Argp,dm);
80047c6ae99SBarry Smith   while (next) {
80147c6ae99SBarry Smith     Vec *vec;
80247c6ae99SBarry Smith     vec = va_arg(Argp, Vec*);
80306930112SJed Brown     if (vec) {ierr = DMGetLocalVector(next->dm,vec);CHKERRQ(ierr);}
80447c6ae99SBarry Smith     next = next->next;
80547c6ae99SBarry Smith   }
80647c6ae99SBarry Smith   va_end(Argp);
80747c6ae99SBarry Smith   PetscFunctionReturn(0);
80847c6ae99SBarry Smith }
80947c6ae99SBarry Smith 
81047c6ae99SBarry Smith #undef __FUNCT__
81147c6ae99SBarry Smith #define __FUNCT__ "DMCompositeRestoreLocalVectors"
81247c6ae99SBarry Smith /*@C
8139ae5db72SJed Brown     DMCompositeRestoreLocalVectors - Restores local vectors for each part of a DMComposite.
81447c6ae99SBarry Smith 
81547c6ae99SBarry Smith     Not Collective
81647c6ae99SBarry Smith 
81747c6ae99SBarry Smith     Input Parameter:
81847c6ae99SBarry Smith .    dm - the packer object
81947c6ae99SBarry Smith 
82047c6ae99SBarry Smith     Output Parameter:
8219ae5db72SJed Brown .   Vec ... - the individual sequential Vecs
82247c6ae99SBarry Smith 
82347c6ae99SBarry Smith     Level: advanced
82447c6ae99SBarry Smith 
8259ae5db72SJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(),
8266eb61c8cSJed Brown          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
82747c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeScatter(), DMCompositeGetEntries()
82847c6ae99SBarry Smith 
82947c6ae99SBarry Smith @*/
8307087cfbeSBarry Smith PetscErrorCode  DMCompositeRestoreLocalVectors(DM dm,...)
83147c6ae99SBarry Smith {
83247c6ae99SBarry Smith   va_list                Argp;
83347c6ae99SBarry Smith   PetscErrorCode         ierr;
83447c6ae99SBarry Smith   struct DMCompositeLink *next;
83547c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
83647c6ae99SBarry Smith 
83747c6ae99SBarry Smith   PetscFunctionBegin;
83847c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
83947c6ae99SBarry Smith   next = com->next;
84047c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
84147c6ae99SBarry Smith   va_start(Argp,dm);
84247c6ae99SBarry Smith   while (next) {
84347c6ae99SBarry Smith     Vec *vec;
84447c6ae99SBarry Smith     vec = va_arg(Argp, Vec*);
84506930112SJed Brown     if (vec) {ierr = DMRestoreLocalVector(next->dm,vec);CHKERRQ(ierr);}
84647c6ae99SBarry Smith     next = next->next;
84747c6ae99SBarry Smith   }
84847c6ae99SBarry Smith   va_end(Argp);
84947c6ae99SBarry Smith   PetscFunctionReturn(0);
85047c6ae99SBarry Smith }
85147c6ae99SBarry Smith 
85247c6ae99SBarry Smith /* -------------------------------------------------------------------------------------*/
85347c6ae99SBarry Smith #undef __FUNCT__
85447c6ae99SBarry Smith #define __FUNCT__ "DMCompositeGetEntries"
85547c6ae99SBarry Smith /*@C
8569ae5db72SJed Brown     DMCompositeGetEntries - Gets the DM for each entry in a DMComposite.
85747c6ae99SBarry Smith 
85847c6ae99SBarry Smith     Not Collective
85947c6ae99SBarry Smith 
86047c6ae99SBarry Smith     Input Parameter:
86147c6ae99SBarry Smith .    dm - the packer object
86247c6ae99SBarry Smith 
86347c6ae99SBarry Smith     Output Parameter:
8649ae5db72SJed Brown .   DM ... - the individual entries (DMs)
86547c6ae99SBarry Smith 
86647c6ae99SBarry Smith     Level: advanced
86747c6ae99SBarry Smith 
8682fa5ba8aSJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(), DMCompositeGetEntriesArray()
8696eb61c8cSJed Brown          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
87047c6ae99SBarry Smith          DMCompositeRestoreLocalVectors(), DMCompositeGetLocalVectors(),  DMCompositeScatter(),
87147c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors()
87247c6ae99SBarry Smith 
87347c6ae99SBarry Smith @*/
8747087cfbeSBarry Smith PetscErrorCode  DMCompositeGetEntries(DM dm,...)
87547c6ae99SBarry Smith {
87647c6ae99SBarry Smith   va_list                Argp;
87747c6ae99SBarry Smith   struct DMCompositeLink *next;
87847c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
87947c6ae99SBarry Smith 
88047c6ae99SBarry Smith   PetscFunctionBegin;
88147c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
88247c6ae99SBarry Smith   next = com->next;
88347c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
88447c6ae99SBarry Smith   va_start(Argp,dm);
88547c6ae99SBarry Smith   while (next) {
88647c6ae99SBarry Smith     DM *dmn;
88747c6ae99SBarry Smith     dmn = va_arg(Argp, DM*);
8889ae5db72SJed Brown     if (dmn) *dmn = next->dm;
88947c6ae99SBarry Smith     next = next->next;
89047c6ae99SBarry Smith   }
89147c6ae99SBarry Smith   va_end(Argp);
89247c6ae99SBarry Smith   PetscFunctionReturn(0);
89347c6ae99SBarry Smith }
89447c6ae99SBarry Smith 
89547c6ae99SBarry Smith #undef __FUNCT__
8962fa5ba8aSJed Brown #define __FUNCT__ "DMCompositeGetEntriesArray"
897dbab29e1SMark F. Adams /*@C
8982fa5ba8aSJed Brown     DMCompositeGetEntriesArray - Gets the DM for each entry in a DMComposite.
8992fa5ba8aSJed Brown 
9002fa5ba8aSJed Brown     Not Collective
9012fa5ba8aSJed Brown 
9022fa5ba8aSJed Brown     Input Parameter:
9032fa5ba8aSJed Brown +    dm - the packer object
9042fa5ba8aSJed Brown -    dms - array of sufficient length (see DMCompositeGetNumberDM()), holds the DMs on output
9052fa5ba8aSJed Brown 
9062fa5ba8aSJed Brown     Level: advanced
9072fa5ba8aSJed Brown 
9082fa5ba8aSJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCreateGlobalVector(), DMCompositeGetEntries()
9092fa5ba8aSJed Brown          DMCompositeGather(), DMCompositeCreate(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess(),
9102fa5ba8aSJed Brown          DMCompositeRestoreLocalVectors(), DMCompositeGetLocalVectors(),  DMCompositeScatter(),
9112fa5ba8aSJed Brown          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors()
9122fa5ba8aSJed Brown 
9132fa5ba8aSJed Brown @*/
9142fa5ba8aSJed Brown PetscErrorCode DMCompositeGetEntriesArray(DM dm,DM dms[])
9152fa5ba8aSJed Brown {
9162fa5ba8aSJed Brown   struct DMCompositeLink *next;
9172fa5ba8aSJed Brown   DM_Composite           *com = (DM_Composite*)dm->data;
9182fa5ba8aSJed Brown   PetscInt               i;
9192fa5ba8aSJed Brown 
9202fa5ba8aSJed Brown   PetscFunctionBegin;
9212fa5ba8aSJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
9222fa5ba8aSJed Brown   /* loop over packed objects, handling one at at time */
9232fa5ba8aSJed Brown   for (next=com->next,i=0; next; next=next->next,i++) dms[i] = next->dm;
9242fa5ba8aSJed Brown   PetscFunctionReturn(0);
9252fa5ba8aSJed Brown }
9262fa5ba8aSJed Brown 
9272fa5ba8aSJed Brown #undef __FUNCT__
9280c010503SBarry Smith #define __FUNCT__ "DMRefine_Composite"
9297087cfbeSBarry Smith PetscErrorCode  DMRefine_Composite(DM dmi,MPI_Comm comm,DM *fine)
93047c6ae99SBarry Smith {
93147c6ae99SBarry Smith   PetscErrorCode         ierr;
93247c6ae99SBarry Smith   struct DMCompositeLink *next;
93347c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dmi->data;
93447c6ae99SBarry Smith   DM                     dm;
93547c6ae99SBarry Smith 
93647c6ae99SBarry Smith   PetscFunctionBegin;
93747c6ae99SBarry Smith   PetscValidHeaderSpecific(dmi,DM_CLASSID,1);
9382ee06e3bSJed Brown   if (comm == MPI_COMM_NULL) comm = ((PetscObject)dmi)->comm;
9392ce3a92bSJed Brown   ierr = DMSetUp(dmi);CHKERRQ(ierr);
94047c6ae99SBarry Smith   next = com->next;
94147c6ae99SBarry Smith   ierr = DMCompositeCreate(comm,fine);CHKERRQ(ierr);
94247c6ae99SBarry Smith 
94347c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
94447c6ae99SBarry Smith   while (next) {
94547c6ae99SBarry Smith     ierr = DMRefine(next->dm,comm,&dm);CHKERRQ(ierr);
94647c6ae99SBarry Smith     ierr = DMCompositeAddDM(*fine,dm);CHKERRQ(ierr);
94747c6ae99SBarry Smith     ierr = PetscObjectDereference((PetscObject)dm);CHKERRQ(ierr);
94847c6ae99SBarry Smith     next = next->next;
94947c6ae99SBarry Smith   }
95047c6ae99SBarry Smith   PetscFunctionReturn(0);
95147c6ae99SBarry Smith }
95247c6ae99SBarry Smith 
95314354c39SJed Brown #undef __FUNCT__
95414354c39SJed Brown #define __FUNCT__ "DMCoarsen_Composite"
95514354c39SJed Brown PetscErrorCode  DMCoarsen_Composite(DM dmi,MPI_Comm comm,DM *fine)
95614354c39SJed Brown {
95714354c39SJed Brown   PetscErrorCode         ierr;
95814354c39SJed Brown   struct DMCompositeLink *next;
95914354c39SJed Brown   DM_Composite           *com = (DM_Composite*)dmi->data;
96014354c39SJed Brown   DM                     dm;
96114354c39SJed Brown 
96214354c39SJed Brown   PetscFunctionBegin;
96314354c39SJed Brown   PetscValidHeaderSpecific(dmi,DM_CLASSID,1);
9642ce3a92bSJed Brown   ierr = DMSetUp(dmi);CHKERRQ(ierr);
9652ee06e3bSJed Brown   if (comm == MPI_COMM_NULL) {
96625296bd5SBarry Smith     ierr = PetscObjectGetComm((PetscObject)dmi,&comm);CHKERRQ(ierr);
96725296bd5SBarry Smith   }
96814354c39SJed Brown   next = com->next;
96914354c39SJed Brown   ierr = DMCompositeCreate(comm,fine);CHKERRQ(ierr);
97014354c39SJed Brown 
97114354c39SJed Brown   /* loop over packed objects, handling one at at time */
97214354c39SJed Brown   while (next) {
97314354c39SJed Brown     ierr = DMCoarsen(next->dm,comm,&dm);CHKERRQ(ierr);
97414354c39SJed Brown     ierr = DMCompositeAddDM(*fine,dm);CHKERRQ(ierr);
97514354c39SJed Brown     ierr = PetscObjectDereference((PetscObject)dm);CHKERRQ(ierr);
97614354c39SJed Brown     next = next->next;
97714354c39SJed Brown   }
97814354c39SJed Brown   PetscFunctionReturn(0);
97914354c39SJed Brown }
98047c6ae99SBarry Smith 
98147c6ae99SBarry Smith #undef __FUNCT__
982e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_Composite"
983e727c939SJed Brown PetscErrorCode  DMCreateInterpolation_Composite(DM coarse,DM fine,Mat *A,Vec *v)
98447c6ae99SBarry Smith {
98547c6ae99SBarry Smith   PetscErrorCode         ierr;
9869ae5db72SJed Brown   PetscInt               m,n,M,N,nDM,i;
98747c6ae99SBarry Smith   struct DMCompositeLink *nextc;
98847c6ae99SBarry Smith   struct DMCompositeLink *nextf;
98925296bd5SBarry Smith   Vec                    gcoarse,gfine,*vecs;
99047c6ae99SBarry Smith   DM_Composite           *comcoarse = (DM_Composite*)coarse->data;
99147c6ae99SBarry Smith   DM_Composite           *comfine   = (DM_Composite*)fine->data;
9929ae5db72SJed Brown   Mat                    *mats;
99347c6ae99SBarry Smith 
99447c6ae99SBarry Smith   PetscFunctionBegin;
99547c6ae99SBarry Smith   PetscValidHeaderSpecific(coarse,DM_CLASSID,1);
99647c6ae99SBarry Smith   PetscValidHeaderSpecific(fine,DM_CLASSID,2);
997f692024eSJed Brown   ierr = DMSetUp(coarse);CHKERRQ(ierr);
998f692024eSJed Brown   ierr = DMSetUp(fine);CHKERRQ(ierr);
99947c6ae99SBarry Smith   /* use global vectors only for determining matrix layout */
10009ae5db72SJed Brown   ierr = DMGetGlobalVector(coarse,&gcoarse);CHKERRQ(ierr);
10019ae5db72SJed Brown   ierr = DMGetGlobalVector(fine,&gfine);CHKERRQ(ierr);
100247c6ae99SBarry Smith   ierr = VecGetLocalSize(gcoarse,&n);CHKERRQ(ierr);
100347c6ae99SBarry Smith   ierr = VecGetLocalSize(gfine,&m);CHKERRQ(ierr);
100447c6ae99SBarry Smith   ierr = VecGetSize(gcoarse,&N);CHKERRQ(ierr);
100547c6ae99SBarry Smith   ierr = VecGetSize(gfine,&M);CHKERRQ(ierr);
10069ae5db72SJed Brown   ierr = DMRestoreGlobalVector(coarse,&gcoarse);CHKERRQ(ierr);
10079ae5db72SJed Brown   ierr = DMRestoreGlobalVector(fine,&gfine);CHKERRQ(ierr);
100847c6ae99SBarry Smith 
10099ae5db72SJed Brown   nDM = comfine->nDM;
10109ae5db72SJed Brown   if (nDM != comcoarse->nDM) SETERRQ2(((PetscObject)fine)->comm,PETSC_ERR_ARG_INCOMP,"Fine DMComposite has %D entries, but coarse has %D",nDM,comcoarse->nDM);
10119ae5db72SJed Brown   ierr = PetscMalloc(nDM*nDM*sizeof(Mat),&mats);CHKERRQ(ierr);
10129ae5db72SJed Brown   ierr = PetscMemzero(mats,nDM*nDM*sizeof(Mat));CHKERRQ(ierr);
101325296bd5SBarry Smith   if (v) {
101425296bd5SBarry Smith     ierr = PetscMalloc(nDM*sizeof(Vec),&vecs);CHKERRQ(ierr);
101525296bd5SBarry Smith     ierr = PetscMemzero(vecs,nDM*sizeof(Vec));CHKERRQ(ierr);
101625296bd5SBarry Smith   }
101747c6ae99SBarry Smith 
101847c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
10199ae5db72SJed Brown   for (nextc=comcoarse->next,nextf=comfine->next,i=0; nextc; nextc=nextc->next,nextf=nextf->next,i++) {
102025296bd5SBarry Smith     if (!v) {
1021e727c939SJed Brown       ierr = DMCreateInterpolation(nextc->dm,nextf->dm,&mats[i*nDM+i],PETSC_NULL);CHKERRQ(ierr);
102225296bd5SBarry Smith     } else {
102325296bd5SBarry Smith       ierr = DMCreateInterpolation(nextc->dm,nextf->dm,&mats[i*nDM+i],&vecs[i]);CHKERRQ(ierr);
102425296bd5SBarry Smith     }
102547c6ae99SBarry Smith   }
10269ae5db72SJed Brown   ierr = MatCreateNest(((PetscObject)fine)->comm,nDM,PETSC_NULL,nDM,PETSC_NULL,mats,A);CHKERRQ(ierr);
102725296bd5SBarry Smith   if (v) {
102825296bd5SBarry Smith     ierr = VecCreateNest(((PetscObject)fine)->comm,nDM,PETSC_NULL,vecs,v);CHKERRQ(ierr);
102925296bd5SBarry Smith   }
10309ae5db72SJed Brown   for (i=0; i<nDM*nDM; i++) {ierr = MatDestroy(&mats[i]);CHKERRQ(ierr);}
10319ae5db72SJed Brown   ierr = PetscFree(mats);CHKERRQ(ierr);
103225296bd5SBarry Smith   if (v) {
103325296bd5SBarry Smith     for (i=0; i<nDM; i++) {ierr = VecDestroy(&vecs[i]);CHKERRQ(ierr);}
103425296bd5SBarry Smith     ierr = PetscFree(vecs);CHKERRQ(ierr);
103525296bd5SBarry Smith   }
103647c6ae99SBarry Smith   PetscFunctionReturn(0);
103747c6ae99SBarry Smith }
103847c6ae99SBarry Smith 
103947c6ae99SBarry Smith #undef __FUNCT__
10401411c6eeSJed Brown #define __FUNCT__ "DMCreateLocalToGlobalMapping_Composite"
10411411c6eeSJed Brown static PetscErrorCode DMCreateLocalToGlobalMapping_Composite(DM dm)
10421411c6eeSJed Brown {
10431411c6eeSJed Brown   DM_Composite           *com = (DM_Composite*)dm->data;
10441411c6eeSJed Brown   ISLocalToGlobalMapping *ltogs;
1045f7efa3c7SJed Brown   PetscInt               i;
10461411c6eeSJed Brown   PetscErrorCode         ierr;
10471411c6eeSJed Brown 
10481411c6eeSJed Brown   PetscFunctionBegin;
10491411c6eeSJed Brown   /* Set the ISLocalToGlobalMapping on the new matrix */
10501411c6eeSJed Brown   ierr = DMCompositeGetISLocalToGlobalMappings(dm,&ltogs);CHKERRQ(ierr);
10519ae5db72SJed Brown   ierr = ISLocalToGlobalMappingConcatenate(((PetscObject)dm)->comm,com->nDM,ltogs,&dm->ltogmap);CHKERRQ(ierr);
10529ae5db72SJed Brown   for (i=0; i<com->nDM; i++) {ierr = ISLocalToGlobalMappingDestroy(&ltogs[i]);CHKERRQ(ierr);}
10531411c6eeSJed Brown   ierr = PetscFree(ltogs);CHKERRQ(ierr);
10541411c6eeSJed Brown   PetscFunctionReturn(0);
10551411c6eeSJed Brown }
10561411c6eeSJed Brown 
10571411c6eeSJed Brown 
10581411c6eeSJed Brown #undef __FUNCT__
1059e727c939SJed Brown #define __FUNCT__ "DMCreateColoring_Composite"
106019fd82e9SBarry Smith PetscErrorCode  DMCreateColoring_Composite(DM dm,ISColoringType ctype,MatType mtype,ISColoring *coloring)
106147c6ae99SBarry Smith {
106247c6ae99SBarry Smith   PetscErrorCode  ierr;
106347c6ae99SBarry Smith   PetscInt        n,i,cnt;
106447c6ae99SBarry Smith   ISColoringValue *colors;
106547c6ae99SBarry Smith   PetscBool       dense  = PETSC_FALSE;
106647c6ae99SBarry Smith   ISColoringValue maxcol = 0;
106747c6ae99SBarry Smith   DM_Composite    *com   = (DM_Composite*)dm->data;
106847c6ae99SBarry Smith 
106947c6ae99SBarry Smith   PetscFunctionBegin;
107047c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
10719805c61eSBarry Smith   if (ctype == IS_COLORING_GHOSTED) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Only global coloring supported");
1072e3247f34SBarry Smith   else if (ctype == IS_COLORING_GLOBAL) {
107347c6ae99SBarry Smith     n = com->n;
107447c6ae99SBarry Smith   } else SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Unknown ISColoringType");
107547c6ae99SBarry Smith   ierr = PetscMalloc(n*sizeof(ISColoringValue),&colors);CHKERRQ(ierr); /* freed in ISColoringDestroy() */
107647c6ae99SBarry Smith 
1077671f6225SBarry Smith   ierr = PetscOptionsGetBool(PETSC_NULL,"-dmcomposite_dense_jacobian",&dense,PETSC_NULL);CHKERRQ(ierr);
107847c6ae99SBarry Smith   if (dense) {
107947c6ae99SBarry Smith     for (i=0; i<n; i++) {
108047c6ae99SBarry Smith       colors[i] = (ISColoringValue)(com->rstart + i);
108147c6ae99SBarry Smith     }
108247c6ae99SBarry Smith     maxcol = com->N;
108347c6ae99SBarry Smith   } else {
108447c6ae99SBarry Smith     struct DMCompositeLink *next = com->next;
108547c6ae99SBarry Smith     PetscMPIInt            rank;
108647c6ae99SBarry Smith 
108747c6ae99SBarry Smith     ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
108847c6ae99SBarry Smith     cnt  = 0;
108947c6ae99SBarry Smith     while (next) {
109047c6ae99SBarry Smith       ISColoring lcoloring;
109147c6ae99SBarry Smith 
1092e727c939SJed Brown       ierr = DMCreateColoring(next->dm,IS_COLORING_GLOBAL,mtype,&lcoloring);CHKERRQ(ierr);
109347c6ae99SBarry Smith       for (i=0; i<lcoloring->N; i++) {
109447c6ae99SBarry Smith         colors[cnt++] = maxcol + lcoloring->colors[i];
109547c6ae99SBarry Smith       }
109647c6ae99SBarry Smith       maxcol += lcoloring->n;
1097fcfd50ebSBarry Smith       ierr    = ISColoringDestroy(&lcoloring);CHKERRQ(ierr);
109847c6ae99SBarry Smith       next    = next->next;
109947c6ae99SBarry Smith     }
110047c6ae99SBarry Smith   }
110147c6ae99SBarry Smith   ierr = ISColoringCreate(((PetscObject)dm)->comm,maxcol,n,colors,coloring);CHKERRQ(ierr);
110247c6ae99SBarry Smith   PetscFunctionReturn(0);
110347c6ae99SBarry Smith }
110447c6ae99SBarry Smith 
110547c6ae99SBarry Smith #undef __FUNCT__
11060c010503SBarry Smith #define __FUNCT__ "DMGlobalToLocalBegin_Composite"
11077087cfbeSBarry Smith PetscErrorCode  DMGlobalToLocalBegin_Composite(DM dm,Vec gvec,InsertMode mode,Vec lvec)
110847c6ae99SBarry Smith {
110947c6ae99SBarry Smith   PetscErrorCode         ierr;
111047c6ae99SBarry Smith   struct DMCompositeLink *next;
111147c6ae99SBarry Smith   PetscInt               cnt = 3;
111247c6ae99SBarry Smith   PetscMPIInt            rank;
111347c6ae99SBarry Smith   PetscScalar            *garray,*larray;
111447c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite*)dm->data;
111547c6ae99SBarry Smith 
111647c6ae99SBarry Smith   PetscFunctionBegin;
111747c6ae99SBarry Smith   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
111847c6ae99SBarry Smith   PetscValidHeaderSpecific(gvec,VEC_CLASSID,2);
111947c6ae99SBarry Smith   next = com->next;
112047c6ae99SBarry Smith   if (!com->setup) {
1121d7bf68aeSBarry Smith     ierr = DMSetUp(dm);CHKERRQ(ierr);
112247c6ae99SBarry Smith   }
112347c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr);
112447c6ae99SBarry Smith   ierr = VecGetArray(gvec,&garray);CHKERRQ(ierr);
112547c6ae99SBarry Smith   ierr = VecGetArray(lvec,&larray);CHKERRQ(ierr);
112647c6ae99SBarry Smith 
112747c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
112847c6ae99SBarry Smith   while (next) {
112947c6ae99SBarry Smith     Vec      local,global;
113047c6ae99SBarry Smith     PetscInt N;
113147c6ae99SBarry Smith 
113247c6ae99SBarry Smith     ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr);
113347c6ae99SBarry Smith     ierr = VecGetLocalSize(global,&N);CHKERRQ(ierr);
113447c6ae99SBarry Smith     ierr = VecPlaceArray(global,garray);CHKERRQ(ierr);
113547c6ae99SBarry Smith     ierr = DMGetLocalVector(next->dm,&local);CHKERRQ(ierr);
113647c6ae99SBarry Smith     ierr = VecPlaceArray(local,larray);CHKERRQ(ierr);
113747c6ae99SBarry Smith     ierr = DMGlobalToLocalBegin(next->dm,global,mode,local);CHKERRQ(ierr);
113847c6ae99SBarry Smith     ierr = DMGlobalToLocalEnd(next->dm,global,mode,local);CHKERRQ(ierr);
113947c6ae99SBarry Smith     ierr = VecResetArray(global);CHKERRQ(ierr);
114047c6ae99SBarry Smith     ierr = VecResetArray(local);CHKERRQ(ierr);
114147c6ae99SBarry Smith     ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr);
114247c6ae99SBarry Smith     ierr = DMRestoreGlobalVector(next->dm,&local);CHKERRQ(ierr);
114347c6ae99SBarry Smith     cnt++;
114406ebdd98SJed Brown     larray += next->nlocal;
114547c6ae99SBarry Smith     next    = next->next;
114647c6ae99SBarry Smith   }
114747c6ae99SBarry Smith 
114847c6ae99SBarry Smith   ierr = VecRestoreArray(gvec,PETSC_NULL);CHKERRQ(ierr);
114947c6ae99SBarry Smith   ierr = VecRestoreArray(lvec,PETSC_NULL);CHKERRQ(ierr);
115047c6ae99SBarry Smith   PetscFunctionReturn(0);
115147c6ae99SBarry Smith }
115247c6ae99SBarry Smith 
115347c6ae99SBarry Smith #undef __FUNCT__
11540c010503SBarry Smith #define __FUNCT__ "DMGlobalToLocalEnd_Composite"
11557087cfbeSBarry Smith PetscErrorCode  DMGlobalToLocalEnd_Composite(DM dm,Vec gvec,InsertMode mode,Vec lvec)
11560c010503SBarry Smith {
11570c010503SBarry Smith   PetscFunctionBegin;
11580c010503SBarry Smith   PetscFunctionReturn(0);
11590c010503SBarry Smith }
116047c6ae99SBarry Smith 
11616ae3a549SBarry Smith /*MC
11626ae3a549SBarry Smith    DMCOMPOSITE = "composite" - A DM object that is used to manage data for a collection of DMs
11636ae3a549SBarry Smith 
11646ae3a549SBarry Smith 
11656ae3a549SBarry Smith 
11666ae3a549SBarry Smith   Level: intermediate
11676ae3a549SBarry Smith 
11686ae3a549SBarry Smith .seealso: DMType, DMCOMPOSITE, DMDACreate(), DMCreate(), DMSetType(), DMCompositeCreate()
11696ae3a549SBarry Smith M*/
11706ae3a549SBarry Smith 
11716ae3a549SBarry Smith 
1172a4121054SBarry Smith EXTERN_C_BEGIN
1173a4121054SBarry Smith #undef __FUNCT__
1174a4121054SBarry Smith #define __FUNCT__ "DMCreate_Composite"
11757087cfbeSBarry Smith PetscErrorCode  DMCreate_Composite(DM p)
1176a4121054SBarry Smith {
1177a4121054SBarry Smith   PetscErrorCode ierr;
1178a4121054SBarry Smith   DM_Composite   *com;
1179a4121054SBarry Smith 
1180a4121054SBarry Smith   PetscFunctionBegin;
1181a4121054SBarry Smith   ierr      = PetscNewLog(p,DM_Composite,&com);CHKERRQ(ierr);
1182a4121054SBarry Smith   p->data   = com;
1183a4121054SBarry Smith   ierr      = PetscObjectChangeTypeName((PetscObject)p,"DMComposite");CHKERRQ(ierr);
1184a4121054SBarry Smith   com->n    = 0;
1185a4121054SBarry Smith   com->next = PETSC_NULL;
1186a4121054SBarry Smith   com->nDM  = 0;
1187a4121054SBarry Smith 
1188a4121054SBarry Smith   p->ops->createglobalvector              = DMCreateGlobalVector_Composite;
1189a4121054SBarry Smith   p->ops->createlocalvector               = DMCreateLocalVector_Composite;
11901411c6eeSJed Brown   p->ops->createlocaltoglobalmapping      = DMCreateLocalToGlobalMapping_Composite;
11911411c6eeSJed Brown   p->ops->createlocaltoglobalmappingblock = 0;
11924d343eeaSMatthew G Knepley   p->ops->createfieldis                   = DMCreateFieldIS_Composite;
119316621825SDmitry Karpeev   p->ops->createfielddecomposition        = DMCreateFieldDecomposition_Composite;
1194a4121054SBarry Smith   p->ops->refine                          = DMRefine_Composite;
119514354c39SJed Brown   p->ops->coarsen                         = DMCoarsen_Composite;
119625296bd5SBarry Smith   p->ops->createinterpolation             = DMCreateInterpolation_Composite;
119725296bd5SBarry Smith   p->ops->creatematrix                    = DMCreateMatrix_Composite;
1198e727c939SJed Brown   p->ops->getcoloring                     = DMCreateColoring_Composite;
1199a4121054SBarry Smith   p->ops->globaltolocalbegin              = DMGlobalToLocalBegin_Composite;
1200a4121054SBarry Smith   p->ops->globaltolocalend                = DMGlobalToLocalEnd_Composite;
1201a4121054SBarry Smith   p->ops->destroy                         = DMDestroy_Composite;
1202a4121054SBarry Smith   p->ops->view                            = DMView_Composite;
1203a4121054SBarry Smith   p->ops->setup                           = DMSetUp_Composite;
1204a4121054SBarry Smith   PetscFunctionReturn(0);
1205a4121054SBarry Smith }
1206a4121054SBarry Smith EXTERN_C_END
1207a4121054SBarry Smith 
12080c010503SBarry Smith #undef __FUNCT__
12090c010503SBarry Smith #define __FUNCT__ "DMCompositeCreate"
12100c010503SBarry Smith /*@C
12110c010503SBarry Smith     DMCompositeCreate - Creates a vector packer, used to generate "composite"
12120c010503SBarry Smith       vectors made up of several subvectors.
12130c010503SBarry Smith 
12140c010503SBarry Smith     Collective on MPI_Comm
121547c6ae99SBarry Smith 
121647c6ae99SBarry Smith     Input Parameter:
12170c010503SBarry Smith .   comm - the processors that will share the global vector
12180c010503SBarry Smith 
12190c010503SBarry Smith     Output Parameters:
12200c010503SBarry Smith .   packer - the packer object
122147c6ae99SBarry Smith 
122247c6ae99SBarry Smith     Level: advanced
122347c6ae99SBarry Smith 
12249ae5db72SJed Brown .seealso DMDestroy(), DMCompositeAddDM(), DMCompositeScatter(),
12256eb61c8cSJed Brown          DMCompositeGather(), DMCreateGlobalVector(), DMCompositeGetISLocalToGlobalMappings(), DMCompositeGetAccess()
122647c6ae99SBarry Smith          DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries()
122747c6ae99SBarry Smith 
122847c6ae99SBarry Smith @*/
12297087cfbeSBarry Smith PetscErrorCode  DMCompositeCreate(MPI_Comm comm,DM *packer)
123047c6ae99SBarry Smith {
12310c010503SBarry Smith   PetscErrorCode ierr;
12320c010503SBarry Smith 
123347c6ae99SBarry Smith   PetscFunctionBegin;
12340c010503SBarry Smith   PetscValidPointer(packer,2);
1235a4121054SBarry Smith   ierr = DMCreate(comm,packer);CHKERRQ(ierr);
1236a4121054SBarry Smith   ierr = DMSetType(*packer,DMCOMPOSITE);CHKERRQ(ierr);
123747c6ae99SBarry Smith   PetscFunctionReturn(0);
123847c6ae99SBarry Smith }
1239