xref: /petsc/src/dm/impls/composite/pack.c (revision dce8aeba1c9b69b19f651c53d8a6b674bd7e9cbd)
147c6ae99SBarry Smith 
2ccd284c7SBarry Smith #include <../src/dm/impls/composite/packimpl.h> /*I  "petscdmcomposite.h"  I*/
3af0996ceSBarry Smith #include <petsc/private/isimpl.h>
4e10fd815SStefano Zampini #include <petsc/private/glvisviewerimpl.h>
52764a2aaSMatthew G. Knepley #include <petscds.h>
647c6ae99SBarry Smith 
747c6ae99SBarry Smith /*@C
847c6ae99SBarry Smith     DMCompositeSetCoupling - Sets user provided routines that compute the coupling between the
9*dce8aebaSBarry Smith       separate components `DM` in a `DMCOMPOSITE` to build the correct matrix nonzero structure.
1047c6ae99SBarry Smith 
11d083f849SBarry Smith     Logically Collective
1247c6ae99SBarry Smith 
13d8d19677SJose E. Roman     Input Parameters:
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 
19*dce8aebaSBarry Smith     Note:
20*dce8aebaSBarry Smith     See `DMSetApplicationContext()` and `DMGetApplicationContext()` for how to get user information into
2147c6ae99SBarry Smith     this routine
2247c6ae99SBarry Smith 
23*dce8aebaSBarry Smith     Fortran Note:
24*dce8aebaSBarry Smith     Not available from Fortran
25*dce8aebaSBarry Smith 
26*dce8aebaSBarry Smith .seealso: `DMCOMPOSITE`, `DM`
2747c6ae99SBarry Smith @*/
28d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompositeSetCoupling(DM dm, PetscErrorCode (*FormCoupleLocations)(DM, Mat, PetscInt *, PetscInt *, PetscInt, PetscInt, PetscInt, PetscInt))
29d71ae5a4SJacob Faibussowitsch {
3047c6ae99SBarry Smith   DM_Composite *com = (DM_Composite *)dm->data;
3171b14b3eSStefano Zampini   PetscBool     flg;
3247c6ae99SBarry Smith 
3347c6ae99SBarry Smith   PetscFunctionBegin;
349566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
357a8be351SBarry Smith   PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
3647c6ae99SBarry Smith   com->FormCoupleLocations = FormCoupleLocations;
3747c6ae99SBarry Smith   PetscFunctionReturn(0);
3847c6ae99SBarry Smith }
3947c6ae99SBarry Smith 
40d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Composite(DM dm)
41d71ae5a4SJacob Faibussowitsch {
4247c6ae99SBarry Smith   struct DMCompositeLink *next, *prev;
4347c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite *)dm->data;
4447c6ae99SBarry Smith 
4547c6ae99SBarry Smith   PetscFunctionBegin;
4647c6ae99SBarry Smith   next = com->next;
4747c6ae99SBarry Smith   while (next) {
4847c6ae99SBarry Smith     prev = next;
4947c6ae99SBarry Smith     next = next->next;
509566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&prev->dm));
519566063dSJacob Faibussowitsch     PetscCall(PetscFree(prev->grstarts));
529566063dSJacob Faibussowitsch     PetscCall(PetscFree(prev));
5347c6ae99SBarry Smith   }
549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL));
55435a35e8SMatthew G Knepley   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
569566063dSJacob Faibussowitsch   PetscCall(PetscFree(com));
5747c6ae99SBarry Smith   PetscFunctionReturn(0);
5847c6ae99SBarry Smith }
5947c6ae99SBarry Smith 
60d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Composite(DM dm, PetscViewer v)
61d71ae5a4SJacob Faibussowitsch {
6247c6ae99SBarry Smith   PetscBool     iascii;
6347c6ae99SBarry Smith   DM_Composite *com = (DM_Composite *)dm->data;
6447c6ae99SBarry Smith 
6547c6ae99SBarry Smith   PetscFunctionBegin;
669566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii));
6747c6ae99SBarry Smith   if (iascii) {
6847c6ae99SBarry Smith     struct DMCompositeLink *lnk = com->next;
6947c6ae99SBarry Smith     PetscInt                i;
7047c6ae99SBarry Smith 
719566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(v, "DM (%s)\n", ((PetscObject)dm)->prefix ? ((PetscObject)dm)->prefix : "no prefix"));
7263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(v, "  contains %" PetscInt_FMT " DMs\n", com->nDM));
739566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(v));
7447c6ae99SBarry Smith     for (i = 0; lnk; lnk = lnk->next, i++) {
7563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(v, "Link %" PetscInt_FMT ": DM of type %s\n", i, ((PetscObject)lnk->dm)->type_name));
769566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(v));
779566063dSJacob Faibussowitsch       PetscCall(DMView(lnk->dm, v));
789566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(v));
7947c6ae99SBarry Smith     }
809566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(v));
8147c6ae99SBarry Smith   }
8247c6ae99SBarry Smith   PetscFunctionReturn(0);
8347c6ae99SBarry Smith }
8447c6ae99SBarry Smith 
8547c6ae99SBarry Smith /* --------------------------------------------------------------------------------------*/
86d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Composite(DM dm)
87d71ae5a4SJacob Faibussowitsch {
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;
9528b400f6SJacob Faibussowitsch   PetscCheck(!com->setup, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Packer has already been setup");
969566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &map));
979566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(map, com->n));
989566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetSize(map, PETSC_DETERMINE));
999566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(map, 1));
1009566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(map));
1019566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetSize(map, &com->N));
1029566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRange(map, &com->rstart, NULL));
1039566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&map));
10447c6ae99SBarry Smith 
1059ae5db72SJed Brown   /* now set the rstart for each linked vector */
1069566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
1079566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
10847c6ae99SBarry Smith   while (next) {
10947c6ae99SBarry Smith     next->rstart = nprev;
11006ebdd98SJed Brown     nprev += next->n;
11147c6ae99SBarry Smith     next->grstart = com->rstart + next->rstart;
1129566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &next->grstarts));
1139566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allgather(&next->grstart, 1, MPIU_INT, next->grstarts, 1, MPIU_INT, PetscObjectComm((PetscObject)dm)));
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 
12273e31fe2SJed Brown /*@
123*dce8aebaSBarry Smith     DMCompositeGetNumberDM - Get's the number of `DM` objects in the `DMCOMPOSITE`
12447c6ae99SBarry Smith        representation.
12547c6ae99SBarry Smith 
12647c6ae99SBarry Smith     Not Collective
12747c6ae99SBarry Smith 
12847c6ae99SBarry Smith     Input Parameter:
129*dce8aebaSBarry Smith .    dm - the `DMCOMPOSITE` object
13047c6ae99SBarry Smith 
13147c6ae99SBarry Smith     Output Parameter:
132*dce8aebaSBarry Smith .     nDM - the number of `DM`
13347c6ae99SBarry Smith 
13447c6ae99SBarry Smith     Level: beginner
13547c6ae99SBarry Smith 
136*dce8aebaSBarry Smith .seealso: `DMCOMPOSITE`, `DM`
13747c6ae99SBarry Smith @*/
138d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompositeGetNumberDM(DM dm, PetscInt *nDM)
139d71ae5a4SJacob Faibussowitsch {
14047c6ae99SBarry Smith   DM_Composite *com = (DM_Composite *)dm->data;
14171b14b3eSStefano Zampini   PetscBool     flg;
1425fd66863SKarl Rupp 
14347c6ae99SBarry Smith   PetscFunctionBegin;
14447c6ae99SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1459566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
1467a8be351SBarry Smith   PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
14747c6ae99SBarry Smith   *nDM = com->nDM;
14847c6ae99SBarry Smith   PetscFunctionReturn(0);
14947c6ae99SBarry Smith }
15047c6ae99SBarry Smith 
15147c6ae99SBarry Smith /*@C
15247c6ae99SBarry Smith     DMCompositeGetAccess - Allows one to access the individual packed vectors in their global
15347c6ae99SBarry Smith        representation.
15447c6ae99SBarry Smith 
155d083f849SBarry Smith     Collective on dm
15647c6ae99SBarry Smith 
1579ae5db72SJed Brown     Input Parameters:
158*dce8aebaSBarry Smith +    dm - the `DMCOMPOSITE` object
1599ae5db72SJed Brown -    gvec - the global vector
1609ae5db72SJed Brown 
1619ae5db72SJed Brown     Output Parameters:
1620298fd71SBarry Smith .    Vec* ... - the packed parallel vectors, NULL for those that are not needed
16347c6ae99SBarry Smith 
16447c6ae99SBarry Smith     Level: advanced
16547c6ae99SBarry Smith 
166*dce8aebaSBarry Smith     Note:
167*dce8aebaSBarry Smith     Use `DMCompositeRestoreAccess()` to return the vectors when you no longer need them
168*dce8aebaSBarry Smith 
169*dce8aebaSBarry Smith     Fortran Note:
170*dce8aebaSBarry Smith     Fortran callers must use numbered versions of this routine, e.g., DMCompositeGetAccess4(dm,gvec,vec1,vec2,vec3,vec4)
171*dce8aebaSBarry Smith     or use the alternative interface `DMCompositeGetAccessArray()`.
172*dce8aebaSBarry Smith 
173*dce8aebaSBarry Smith .seealso: `DMCOMPOSITE`, `DM`, `DMCompositeGetEntries()`, `DMCompositeScatter()`
17447c6ae99SBarry Smith @*/
175d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompositeGetAccess(DM dm, Vec gvec, ...)
176d71ae5a4SJacob Faibussowitsch {
17747c6ae99SBarry Smith   va_list                 Argp;
17847c6ae99SBarry Smith   struct DMCompositeLink *next;
17947c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite *)dm->data;
1805edff71fSBarry Smith   PetscInt                readonly;
18171b14b3eSStefano Zampini   PetscBool               flg;
18247c6ae99SBarry Smith 
18347c6ae99SBarry Smith   PetscFunctionBegin;
18447c6ae99SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18547c6ae99SBarry Smith   PetscValidHeaderSpecific(gvec, VEC_CLASSID, 2);
1869566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
1877a8be351SBarry Smith   PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
18847c6ae99SBarry Smith   next = com->next;
18948a46eb9SPierre Jolivet   if (!com->setup) PetscCall(DMSetUp(dm));
19047c6ae99SBarry Smith 
1919566063dSJacob Faibussowitsch   PetscCall(VecLockGet(gvec, &readonly));
19247c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
19347c6ae99SBarry Smith   va_start(Argp, gvec);
19447c6ae99SBarry Smith   while (next) {
19547c6ae99SBarry Smith     Vec *vec;
19647c6ae99SBarry Smith     vec = va_arg(Argp, Vec *);
1979ae5db72SJed Brown     if (vec) {
1989566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalVector(next->dm, vec));
1995edff71fSBarry Smith       if (readonly) {
2005edff71fSBarry Smith         const PetscScalar *array;
2019566063dSJacob Faibussowitsch         PetscCall(VecGetArrayRead(gvec, &array));
2029566063dSJacob Faibussowitsch         PetscCall(VecPlaceArray(*vec, array + next->rstart));
2039566063dSJacob Faibussowitsch         PetscCall(VecLockReadPush(*vec));
2049566063dSJacob Faibussowitsch         PetscCall(VecRestoreArrayRead(gvec, &array));
2055edff71fSBarry Smith       } else {
2065edff71fSBarry Smith         PetscScalar *array;
2079566063dSJacob Faibussowitsch         PetscCall(VecGetArray(gvec, &array));
2089566063dSJacob Faibussowitsch         PetscCall(VecPlaceArray(*vec, array + next->rstart));
2099566063dSJacob Faibussowitsch         PetscCall(VecRestoreArray(gvec, &array));
21047c6ae99SBarry Smith       }
2115edff71fSBarry Smith     }
21247c6ae99SBarry Smith     next = next->next;
21347c6ae99SBarry Smith   }
21447c6ae99SBarry Smith   va_end(Argp);
21547c6ae99SBarry Smith   PetscFunctionReturn(0);
21647c6ae99SBarry Smith }
21747c6ae99SBarry Smith 
218f73e5cebSJed Brown /*@C
219f73e5cebSJed Brown     DMCompositeGetAccessArray - Allows one to access the individual packed vectors in their global
220f73e5cebSJed Brown        representation.
221f73e5cebSJed Brown 
222d083f849SBarry Smith     Collective on dm
223f73e5cebSJed Brown 
224f73e5cebSJed Brown     Input Parameters:
225*dce8aebaSBarry Smith +    dm - the `DMCOMPOSITE`
226f73e5cebSJed Brown .    pvec - packed vector
227f73e5cebSJed Brown .    nwanted - number of vectors wanted
2280298fd71SBarry Smith -    wanted - sorted array of vectors wanted, or NULL to get all vectors
229f73e5cebSJed Brown 
230f73e5cebSJed Brown     Output Parameters:
231f73e5cebSJed Brown .    vecs - array of requested global vectors (must be allocated)
232f73e5cebSJed Brown 
233f73e5cebSJed Brown     Level: advanced
234f73e5cebSJed Brown 
235*dce8aebaSBarry Smith     Note:
236*dce8aebaSBarry Smith     Use `DMCompositeRestoreAccessArray()` to return the vectors when you no longer need them
237*dce8aebaSBarry Smith 
238*dce8aebaSBarry Smith .seealso: `DMCOMPOSITE`, `DM`, `DMCompositeGetAccess()`, `DMCompositeGetEntries()`, `DMCompositeScatter()`, `DMCompositeGather()`
239f73e5cebSJed Brown @*/
240d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompositeGetAccessArray(DM dm, Vec pvec, PetscInt nwanted, const PetscInt *wanted, Vec *vecs)
241d71ae5a4SJacob Faibussowitsch {
242f73e5cebSJed Brown   struct DMCompositeLink *link;
243f73e5cebSJed Brown   PetscInt                i, wnum;
244f73e5cebSJed Brown   DM_Composite           *com = (DM_Composite *)dm->data;
245bee642f7SBarry Smith   PetscInt                readonly;
24671b14b3eSStefano Zampini   PetscBool               flg;
247f73e5cebSJed Brown 
248f73e5cebSJed Brown   PetscFunctionBegin;
249f73e5cebSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
250f73e5cebSJed Brown   PetscValidHeaderSpecific(pvec, VEC_CLASSID, 2);
2519566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
2527a8be351SBarry Smith   PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
25348a46eb9SPierre Jolivet   if (!com->setup) PetscCall(DMSetUp(dm));
254f73e5cebSJed Brown 
2559566063dSJacob Faibussowitsch   PetscCall(VecLockGet(pvec, &readonly));
256f73e5cebSJed Brown   for (i = 0, wnum = 0, link = com->next; link && wnum < nwanted; i++, link = link->next) {
257f73e5cebSJed Brown     if (!wanted || i == wanted[wnum]) {
258f73e5cebSJed Brown       Vec v;
2599566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalVector(link->dm, &v));
260bee642f7SBarry Smith       if (readonly) {
261bee642f7SBarry Smith         const PetscScalar *array;
2629566063dSJacob Faibussowitsch         PetscCall(VecGetArrayRead(pvec, &array));
2639566063dSJacob Faibussowitsch         PetscCall(VecPlaceArray(v, array + link->rstart));
2649566063dSJacob Faibussowitsch         PetscCall(VecLockReadPush(v));
2659566063dSJacob Faibussowitsch         PetscCall(VecRestoreArrayRead(pvec, &array));
266bee642f7SBarry Smith       } else {
267bee642f7SBarry Smith         PetscScalar *array;
2689566063dSJacob Faibussowitsch         PetscCall(VecGetArray(pvec, &array));
2699566063dSJacob Faibussowitsch         PetscCall(VecPlaceArray(v, array + link->rstart));
2709566063dSJacob Faibussowitsch         PetscCall(VecRestoreArray(pvec, &array));
271bee642f7SBarry Smith       }
272f73e5cebSJed Brown       vecs[wnum++] = v;
273f73e5cebSJed Brown     }
274f73e5cebSJed Brown   }
275f73e5cebSJed Brown   PetscFunctionReturn(0);
276f73e5cebSJed Brown }
277f73e5cebSJed Brown 
2787ac2b803SAlex Fikl /*@C
2797ac2b803SAlex Fikl     DMCompositeGetLocalAccessArray - Allows one to access the individual
2807ac2b803SAlex Fikl     packed vectors in their local representation.
2817ac2b803SAlex Fikl 
282d083f849SBarry Smith     Collective on dm.
2837ac2b803SAlex Fikl 
2847ac2b803SAlex Fikl     Input Parameters:
285*dce8aebaSBarry Smith +    dm - the `DMCOMPOSITE`
2867ac2b803SAlex Fikl .    pvec - packed vector
2877ac2b803SAlex Fikl .    nwanted - number of vectors wanted
2887ac2b803SAlex Fikl -    wanted - sorted array of vectors wanted, or NULL to get all vectors
2897ac2b803SAlex Fikl 
2907ac2b803SAlex Fikl     Output Parameters:
2917ac2b803SAlex Fikl .    vecs - array of requested local vectors (must be allocated)
2927ac2b803SAlex Fikl 
2937ac2b803SAlex Fikl     Level: advanced
2947ac2b803SAlex Fikl 
295*dce8aebaSBarry Smith     Note:
296*dce8aebaSBarry Smith     Use `DMCompositeRestoreLocalAccessArray()` to return the vectors
297*dce8aebaSBarry Smith     when you no longer need them.
298*dce8aebaSBarry Smith 
299*dce8aebaSBarry Smith .seealso: `DMCOMPOSITE`, `DM`, `DMCompositeRestoreLocalAccessArray()`, `DMCompositeGetAccess()`,
300db781477SPatrick Sanan           `DMCompositeGetEntries()`, `DMCompositeScatter()`, `DMCompositeGather()`
3017ac2b803SAlex Fikl @*/
302d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompositeGetLocalAccessArray(DM dm, Vec pvec, PetscInt nwanted, const PetscInt *wanted, Vec *vecs)
303d71ae5a4SJacob Faibussowitsch {
3047ac2b803SAlex Fikl   struct DMCompositeLink *link;
3057ac2b803SAlex Fikl   PetscInt                i, wnum;
3067ac2b803SAlex Fikl   DM_Composite           *com = (DM_Composite *)dm->data;
3077ac2b803SAlex Fikl   PetscInt                readonly;
3087ac2b803SAlex Fikl   PetscInt                nlocal = 0;
30971b14b3eSStefano Zampini   PetscBool               flg;
3107ac2b803SAlex Fikl 
3117ac2b803SAlex Fikl   PetscFunctionBegin;
3127ac2b803SAlex Fikl   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3137ac2b803SAlex Fikl   PetscValidHeaderSpecific(pvec, VEC_CLASSID, 2);
3149566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
3157a8be351SBarry Smith   PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
31648a46eb9SPierre Jolivet   if (!com->setup) PetscCall(DMSetUp(dm));
3177ac2b803SAlex Fikl 
3189566063dSJacob Faibussowitsch   PetscCall(VecLockGet(pvec, &readonly));
3197ac2b803SAlex Fikl   for (i = 0, wnum = 0, link = com->next; link && wnum < nwanted; i++, link = link->next) {
3207ac2b803SAlex Fikl     if (!wanted || i == wanted[wnum]) {
3217ac2b803SAlex Fikl       Vec v;
3229566063dSJacob Faibussowitsch       PetscCall(DMGetLocalVector(link->dm, &v));
3237ac2b803SAlex Fikl       if (readonly) {
3247ac2b803SAlex Fikl         const PetscScalar *array;
3259566063dSJacob Faibussowitsch         PetscCall(VecGetArrayRead(pvec, &array));
3269566063dSJacob Faibussowitsch         PetscCall(VecPlaceArray(v, array + nlocal));
327b1c3483dSMark Adams         // this method does not make sense. The local vectors are not updated with a global-to-local and the user can not do it because it is locked
3289566063dSJacob Faibussowitsch         PetscCall(VecLockReadPush(v));
3299566063dSJacob Faibussowitsch         PetscCall(VecRestoreArrayRead(pvec, &array));
3307ac2b803SAlex Fikl       } else {
3317ac2b803SAlex Fikl         PetscScalar *array;
3329566063dSJacob Faibussowitsch         PetscCall(VecGetArray(pvec, &array));
3339566063dSJacob Faibussowitsch         PetscCall(VecPlaceArray(v, array + nlocal));
3349566063dSJacob Faibussowitsch         PetscCall(VecRestoreArray(pvec, &array));
3357ac2b803SAlex Fikl       }
3367ac2b803SAlex Fikl       vecs[wnum++] = v;
3377ac2b803SAlex Fikl     }
3387ac2b803SAlex Fikl 
3397ac2b803SAlex Fikl     nlocal += link->nlocal;
3407ac2b803SAlex Fikl   }
3417ac2b803SAlex Fikl 
3427ac2b803SAlex Fikl   PetscFunctionReturn(0);
3437ac2b803SAlex Fikl }
3447ac2b803SAlex Fikl 
34547c6ae99SBarry Smith /*@C
346*dce8aebaSBarry Smith     DMCompositeRestoreAccess - Returns the vectors obtained with `DMCompositeGetAccess()`
34747c6ae99SBarry Smith        representation.
34847c6ae99SBarry Smith 
349d083f849SBarry Smith     Collective on dm
35047c6ae99SBarry Smith 
3519ae5db72SJed Brown     Input Parameters:
352*dce8aebaSBarry Smith +    dm - the `DMCOMPOSITE` object
35347c6ae99SBarry Smith .    gvec - the global vector
3540298fd71SBarry Smith -    Vec* ... - the individual parallel vectors, NULL for those that are not needed
35547c6ae99SBarry Smith 
35647c6ae99SBarry Smith     Level: advanced
35747c6ae99SBarry Smith 
358*dce8aebaSBarry Smith .seealso: `DMCOMPOSITE`, `DM`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`,
359db781477SPatrick Sanan          `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeScatter()`,
360db781477SPatrick Sanan          `DMCompositeRestoreAccess()`, `DMCompositeGetAccess()`
36147c6ae99SBarry Smith @*/
362d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompositeRestoreAccess(DM dm, Vec gvec, ...)
363d71ae5a4SJacob Faibussowitsch {
36447c6ae99SBarry Smith   va_list                 Argp;
36547c6ae99SBarry Smith   struct DMCompositeLink *next;
36647c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite *)dm->data;
3675edff71fSBarry Smith   PetscInt                readonly;
36871b14b3eSStefano Zampini   PetscBool               flg;
36947c6ae99SBarry Smith 
37047c6ae99SBarry Smith   PetscFunctionBegin;
37147c6ae99SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37247c6ae99SBarry Smith   PetscValidHeaderSpecific(gvec, VEC_CLASSID, 2);
3739566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
3747a8be351SBarry Smith   PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
37547c6ae99SBarry Smith   next = com->next;
37648a46eb9SPierre Jolivet   if (!com->setup) PetscCall(DMSetUp(dm));
37747c6ae99SBarry Smith 
3789566063dSJacob Faibussowitsch   PetscCall(VecLockGet(gvec, &readonly));
37947c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
38047c6ae99SBarry Smith   va_start(Argp, gvec);
38147c6ae99SBarry Smith   while (next) {
38247c6ae99SBarry Smith     Vec *vec;
38347c6ae99SBarry Smith     vec = va_arg(Argp, Vec *);
3849ae5db72SJed Brown     if (vec) {
3859566063dSJacob Faibussowitsch       PetscCall(VecResetArray(*vec));
3861baa6e33SBarry Smith       if (readonly) PetscCall(VecLockReadPop(*vec));
3879566063dSJacob Faibussowitsch       PetscCall(DMRestoreGlobalVector(next->dm, vec));
38847c6ae99SBarry Smith     }
38947c6ae99SBarry Smith     next = next->next;
39047c6ae99SBarry Smith   }
39147c6ae99SBarry Smith   va_end(Argp);
39247c6ae99SBarry Smith   PetscFunctionReturn(0);
39347c6ae99SBarry Smith }
39447c6ae99SBarry Smith 
395f73e5cebSJed Brown /*@C
396*dce8aebaSBarry Smith     DMCompositeRestoreAccessArray - Returns the vectors obtained with `DMCompositeGetAccessArray()`
397f73e5cebSJed Brown 
398d083f849SBarry Smith     Collective on dm
399f73e5cebSJed Brown 
400f73e5cebSJed Brown     Input Parameters:
401*dce8aebaSBarry Smith +    dm - the `DMCOMPOSITE` object
402f73e5cebSJed Brown .    pvec - packed vector
403f73e5cebSJed Brown .    nwanted - number of vectors wanted
4040298fd71SBarry Smith .    wanted - sorted array of vectors wanted, or NULL to get all vectors
405f73e5cebSJed Brown -    vecs - array of global vectors to return
406f73e5cebSJed Brown 
407f73e5cebSJed Brown     Level: advanced
408f73e5cebSJed Brown 
409*dce8aebaSBarry Smith .seealso: `DMCOMPOSITE`, `DM`, `DMCompositeRestoreAccess()`, `DMCompositeRestoreEntries()`, `DMCompositeScatter()`, `DMCompositeGather()`
410f73e5cebSJed Brown @*/
411d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompositeRestoreAccessArray(DM dm, Vec pvec, PetscInt nwanted, const PetscInt *wanted, Vec *vecs)
412d71ae5a4SJacob Faibussowitsch {
413f73e5cebSJed Brown   struct DMCompositeLink *link;
414f73e5cebSJed Brown   PetscInt                i, wnum;
415f73e5cebSJed Brown   DM_Composite           *com = (DM_Composite *)dm->data;
416bee642f7SBarry Smith   PetscInt                readonly;
41771b14b3eSStefano Zampini   PetscBool               flg;
418f73e5cebSJed Brown 
419f73e5cebSJed Brown   PetscFunctionBegin;
420f73e5cebSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
421f73e5cebSJed Brown   PetscValidHeaderSpecific(pvec, VEC_CLASSID, 2);
4229566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
4237a8be351SBarry Smith   PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
42448a46eb9SPierre Jolivet   if (!com->setup) PetscCall(DMSetUp(dm));
425f73e5cebSJed Brown 
4269566063dSJacob Faibussowitsch   PetscCall(VecLockGet(pvec, &readonly));
427f73e5cebSJed Brown   for (i = 0, wnum = 0, link = com->next; link && wnum < nwanted; i++, link = link->next) {
428f73e5cebSJed Brown     if (!wanted || i == wanted[wnum]) {
4299566063dSJacob Faibussowitsch       PetscCall(VecResetArray(vecs[wnum]));
43048a46eb9SPierre Jolivet       if (readonly) PetscCall(VecLockReadPop(vecs[wnum]));
4319566063dSJacob Faibussowitsch       PetscCall(DMRestoreGlobalVector(link->dm, &vecs[wnum]));
432f73e5cebSJed Brown       wnum++;
433f73e5cebSJed Brown     }
434f73e5cebSJed Brown   }
435f73e5cebSJed Brown   PetscFunctionReturn(0);
436f73e5cebSJed Brown }
437f73e5cebSJed Brown 
4387ac2b803SAlex Fikl /*@C
439*dce8aebaSBarry Smith     DMCompositeRestoreLocalAccessArray - Returns the vectors obtained with `DMCompositeGetLocalAccessArray()`.
4407ac2b803SAlex Fikl 
441d083f849SBarry Smith     Collective on dm.
4427ac2b803SAlex Fikl 
4437ac2b803SAlex Fikl     Input Parameters:
444*dce8aebaSBarry Smith +    dm - the `DMCOMPOSITE` object
4457ac2b803SAlex Fikl .    pvec - packed vector
4467ac2b803SAlex Fikl .    nwanted - number of vectors wanted
4477ac2b803SAlex Fikl .    wanted - sorted array of vectors wanted, or NULL to restore all vectors
4487ac2b803SAlex Fikl -    vecs - array of local vectors to return
4497ac2b803SAlex Fikl 
4507ac2b803SAlex Fikl     Level: advanced
4517ac2b803SAlex Fikl 
452*dce8aebaSBarry Smith     Note:
453*dce8aebaSBarry Smith     nwanted and wanted must match the values given to `DMCompositeGetLocalAccessArray()`
4547ac2b803SAlex Fikl     otherwise the call will fail.
4557ac2b803SAlex Fikl 
456*dce8aebaSBarry Smith .seealso: `DMCOMPOSITE`, `DM`, `DMCompositeGetLocalAccessArray()`, `DMCompositeRestoreAccessArray()`,
457db781477SPatrick Sanan           `DMCompositeRestoreAccess()`, `DMCompositeRestoreEntries()`,
458db781477SPatrick Sanan           `DMCompositeScatter()`, `DMCompositeGather()`
4597ac2b803SAlex Fikl @*/
460d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompositeRestoreLocalAccessArray(DM dm, Vec pvec, PetscInt nwanted, const PetscInt *wanted, Vec *vecs)
461d71ae5a4SJacob Faibussowitsch {
4627ac2b803SAlex Fikl   struct DMCompositeLink *link;
4637ac2b803SAlex Fikl   PetscInt                i, wnum;
4647ac2b803SAlex Fikl   DM_Composite           *com = (DM_Composite *)dm->data;
4657ac2b803SAlex Fikl   PetscInt                readonly;
46671b14b3eSStefano Zampini   PetscBool               flg;
4677ac2b803SAlex Fikl 
4687ac2b803SAlex Fikl   PetscFunctionBegin;
4697ac2b803SAlex Fikl   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4707ac2b803SAlex Fikl   PetscValidHeaderSpecific(pvec, VEC_CLASSID, 2);
4719566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
4727a8be351SBarry Smith   PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
47348a46eb9SPierre Jolivet   if (!com->setup) PetscCall(DMSetUp(dm));
4747ac2b803SAlex Fikl 
4759566063dSJacob Faibussowitsch   PetscCall(VecLockGet(pvec, &readonly));
4767ac2b803SAlex Fikl   for (i = 0, wnum = 0, link = com->next; link && wnum < nwanted; i++, link = link->next) {
4777ac2b803SAlex Fikl     if (!wanted || i == wanted[wnum]) {
4789566063dSJacob Faibussowitsch       PetscCall(VecResetArray(vecs[wnum]));
47948a46eb9SPierre Jolivet       if (readonly) PetscCall(VecLockReadPop(vecs[wnum]));
4809566063dSJacob Faibussowitsch       PetscCall(DMRestoreLocalVector(link->dm, &vecs[wnum]));
4817ac2b803SAlex Fikl       wnum++;
4827ac2b803SAlex Fikl     }
4837ac2b803SAlex Fikl   }
4847ac2b803SAlex Fikl   PetscFunctionReturn(0);
4857ac2b803SAlex Fikl }
4867ac2b803SAlex Fikl 
48747c6ae99SBarry Smith /*@C
48847c6ae99SBarry Smith     DMCompositeScatter - Scatters from a global packed vector into its individual local vectors
48947c6ae99SBarry Smith 
490d083f849SBarry Smith     Collective on dm
49147c6ae99SBarry Smith 
4929ae5db72SJed Brown     Input Parameters:
493*dce8aebaSBarry Smith +    dm - the `DMCOMPOSITE` object
49447c6ae99SBarry Smith .    gvec - the global vector
4950298fd71SBarry Smith -    Vec ... - the individual sequential vectors, NULL for those that are not needed
49647c6ae99SBarry Smith 
49747c6ae99SBarry Smith     Level: advanced
49847c6ae99SBarry Smith 
499*dce8aebaSBarry Smith     Note:
500*dce8aebaSBarry Smith     `DMCompositeScatterArray()` is a non-variadic alternative that is often more convenient for library callers and is
5016f3c3dcfSJed Brown     accessible from Fortran.
5026f3c3dcfSJed Brown 
503*dce8aebaSBarry Smith .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`,
504db781477SPatrick Sanan          `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`,
505db781477SPatrick Sanan          `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()`
506db781477SPatrick Sanan          `DMCompositeScatterArray()`
50747c6ae99SBarry Smith @*/
508d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompositeScatter(DM dm, Vec gvec, ...)
509d71ae5a4SJacob Faibussowitsch {
51047c6ae99SBarry Smith   va_list                 Argp;
51147c6ae99SBarry Smith   struct DMCompositeLink *next;
512c599c493SJunchao Zhang   PETSC_UNUSED PetscInt   cnt;
51347c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite *)dm->data;
51471b14b3eSStefano Zampini   PetscBool               flg;
51547c6ae99SBarry Smith 
51647c6ae99SBarry Smith   PetscFunctionBegin;
51747c6ae99SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
51847c6ae99SBarry Smith   PetscValidHeaderSpecific(gvec, VEC_CLASSID, 2);
5199566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
5207a8be351SBarry Smith   PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
52148a46eb9SPierre Jolivet   if (!com->setup) PetscCall(DMSetUp(dm));
52247c6ae99SBarry Smith 
52347c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
52447c6ae99SBarry Smith   va_start(Argp, gvec);
5258fd8f222SJed Brown   for (cnt = 3, next = com->next; next; cnt++, next = next->next) {
5269ae5db72SJed Brown     Vec local;
5279ae5db72SJed Brown     local = va_arg(Argp, Vec);
5289ae5db72SJed Brown     if (local) {
5299ae5db72SJed Brown       Vec                global;
5305edff71fSBarry Smith       const PetscScalar *array;
53163a3b9bcSJacob Faibussowitsch       PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PetscValidHeaderSpecific(local, VEC_CLASSID, (int)cnt));
5329566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalVector(next->dm, &global));
5339566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(gvec, &array));
5349566063dSJacob Faibussowitsch       PetscCall(VecPlaceArray(global, array + next->rstart));
5359566063dSJacob Faibussowitsch       PetscCall(DMGlobalToLocalBegin(next->dm, global, INSERT_VALUES, local));
5369566063dSJacob Faibussowitsch       PetscCall(DMGlobalToLocalEnd(next->dm, global, INSERT_VALUES, local));
5379566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(gvec, &array));
5389566063dSJacob Faibussowitsch       PetscCall(VecResetArray(global));
5399566063dSJacob Faibussowitsch       PetscCall(DMRestoreGlobalVector(next->dm, &global));
54047c6ae99SBarry Smith     }
54147c6ae99SBarry Smith   }
54247c6ae99SBarry Smith   va_end(Argp);
54347c6ae99SBarry Smith   PetscFunctionReturn(0);
54447c6ae99SBarry Smith }
54547c6ae99SBarry Smith 
5466f3c3dcfSJed Brown /*@
5476f3c3dcfSJed Brown     DMCompositeScatterArray - Scatters from a global packed vector into its individual local vectors
5486f3c3dcfSJed Brown 
549d083f849SBarry Smith     Collective on dm
5506f3c3dcfSJed Brown 
5516f3c3dcfSJed Brown     Input Parameters:
552*dce8aebaSBarry Smith +    dm - the `DMCOMPOSITE` object
5536f3c3dcfSJed Brown .    gvec - the global vector
554a2b725a8SWilliam Gropp -    lvecs - array of local vectors, NULL for any that are not needed
5556f3c3dcfSJed Brown 
5566f3c3dcfSJed Brown     Level: advanced
5576f3c3dcfSJed Brown 
5586f3c3dcfSJed Brown     Note:
559*dce8aebaSBarry Smith     This is a non-variadic alternative to `DMCompositeScatter()`
5606f3c3dcfSJed Brown 
561*dce8aebaSBarry Smith .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`
562db781477SPatrick Sanan          `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`,
563db781477SPatrick Sanan          `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()`
5646f3c3dcfSJed Brown @*/
565d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompositeScatterArray(DM dm, Vec gvec, Vec *lvecs)
566d71ae5a4SJacob Faibussowitsch {
5676f3c3dcfSJed Brown   struct DMCompositeLink *next;
5686f3c3dcfSJed Brown   PetscInt                i;
5696f3c3dcfSJed Brown   DM_Composite           *com = (DM_Composite *)dm->data;
57071b14b3eSStefano Zampini   PetscBool               flg;
5716f3c3dcfSJed Brown 
5726f3c3dcfSJed Brown   PetscFunctionBegin;
5736f3c3dcfSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5746f3c3dcfSJed Brown   PetscValidHeaderSpecific(gvec, VEC_CLASSID, 2);
5759566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
5767a8be351SBarry Smith   PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
57748a46eb9SPierre Jolivet   if (!com->setup) PetscCall(DMSetUp(dm));
5786f3c3dcfSJed Brown 
5796f3c3dcfSJed Brown   /* loop over packed objects, handling one at at time */
5806f3c3dcfSJed Brown   for (i = 0, next = com->next; next; next = next->next, i++) {
5816f3c3dcfSJed Brown     if (lvecs[i]) {
5826f3c3dcfSJed Brown       Vec                global;
583c5d31e75SLisandro Dalcin       const PetscScalar *array;
5846f3c3dcfSJed Brown       PetscValidHeaderSpecific(lvecs[i], VEC_CLASSID, 3);
5859566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalVector(next->dm, &global));
5869566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(gvec, &array));
5879566063dSJacob Faibussowitsch       PetscCall(VecPlaceArray(global, (PetscScalar *)array + next->rstart));
5889566063dSJacob Faibussowitsch       PetscCall(DMGlobalToLocalBegin(next->dm, global, INSERT_VALUES, lvecs[i]));
5899566063dSJacob Faibussowitsch       PetscCall(DMGlobalToLocalEnd(next->dm, global, INSERT_VALUES, lvecs[i]));
5909566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(gvec, &array));
5919566063dSJacob Faibussowitsch       PetscCall(VecResetArray(global));
5929566063dSJacob Faibussowitsch       PetscCall(DMRestoreGlobalVector(next->dm, &global));
5936f3c3dcfSJed Brown     }
5946f3c3dcfSJed Brown   }
5956f3c3dcfSJed Brown   PetscFunctionReturn(0);
5966f3c3dcfSJed Brown }
5976f3c3dcfSJed Brown 
59847c6ae99SBarry Smith /*@C
59947c6ae99SBarry Smith     DMCompositeGather - Gathers into a global packed vector from its individual local vectors
60047c6ae99SBarry Smith 
601d083f849SBarry Smith     Collective on dm
60247c6ae99SBarry Smith 
603d8d19677SJose E. Roman     Input Parameters:
604*dce8aebaSBarry Smith +    dm - the `DMCOMPOSITE` object
60547c6ae99SBarry Smith .    gvec - the global vector
606*dce8aebaSBarry Smith .    imode - `INSERT_VALUES` or `ADD_VALUES`
6070298fd71SBarry Smith -    Vec ... - the individual sequential vectors, NULL for any that are not needed
60847c6ae99SBarry Smith 
60947c6ae99SBarry Smith     Level: advanced
61047c6ae99SBarry Smith 
611*dce8aebaSBarry Smith     Fortran Note:
612*dce8aebaSBarry Smith     Fortran users should use `DMCompositeGatherArray()`
613f5f57ec0SBarry Smith 
614*dce8aebaSBarry Smith .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`,
615db781477SPatrick Sanan          `DMCompositeScatter()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`,
616db781477SPatrick Sanan          `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()`
61747c6ae99SBarry Smith @*/
618d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompositeGather(DM dm, InsertMode imode, Vec gvec, ...)
619d71ae5a4SJacob Faibussowitsch {
62047c6ae99SBarry Smith   va_list                 Argp;
62147c6ae99SBarry Smith   struct DMCompositeLink *next;
62247c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite *)dm->data;
623c599c493SJunchao Zhang   PETSC_UNUSED PetscInt   cnt;
62471b14b3eSStefano Zampini   PetscBool               flg;
62547c6ae99SBarry Smith 
62647c6ae99SBarry Smith   PetscFunctionBegin;
62747c6ae99SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
628064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(gvec, VEC_CLASSID, 3);
6299566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
6307a8be351SBarry Smith   PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
63148a46eb9SPierre Jolivet   if (!com->setup) PetscCall(DMSetUp(dm));
63247c6ae99SBarry Smith 
63347c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
6341dac896bSSatish Balay   va_start(Argp, gvec);
6358fd8f222SJed Brown   for (cnt = 3, next = com->next; next; cnt++, next = next->next) {
6369ae5db72SJed Brown     Vec local;
6379ae5db72SJed Brown     local = va_arg(Argp, Vec);
6389ae5db72SJed Brown     if (local) {
63947c6ae99SBarry Smith       PetscScalar *array;
6409ae5db72SJed Brown       Vec          global;
64163a3b9bcSJacob Faibussowitsch       PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PetscValidHeaderSpecific(local, VEC_CLASSID, (int)cnt));
6429566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalVector(next->dm, &global));
6439566063dSJacob Faibussowitsch       PetscCall(VecGetArray(gvec, &array));
6449566063dSJacob Faibussowitsch       PetscCall(VecPlaceArray(global, array + next->rstart));
6459566063dSJacob Faibussowitsch       PetscCall(DMLocalToGlobalBegin(next->dm, local, imode, global));
6469566063dSJacob Faibussowitsch       PetscCall(DMLocalToGlobalEnd(next->dm, local, imode, global));
6479566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(gvec, &array));
6489566063dSJacob Faibussowitsch       PetscCall(VecResetArray(global));
6499566063dSJacob Faibussowitsch       PetscCall(DMRestoreGlobalVector(next->dm, &global));
65047c6ae99SBarry Smith     }
65147c6ae99SBarry Smith   }
65247c6ae99SBarry Smith   va_end(Argp);
65347c6ae99SBarry Smith   PetscFunctionReturn(0);
65447c6ae99SBarry Smith }
65547c6ae99SBarry Smith 
6566f3c3dcfSJed Brown /*@
6576f3c3dcfSJed Brown     DMCompositeGatherArray - Gathers into a global packed vector from its individual local vectors
6586f3c3dcfSJed Brown 
659d083f849SBarry Smith     Collective on dm
6606f3c3dcfSJed Brown 
661d8d19677SJose E. Roman     Input Parameters:
662*dce8aebaSBarry Smith +    dm - the `DMCOMPOSITE` object
6636f3c3dcfSJed Brown .    gvec - the global vector
664*dce8aebaSBarry Smith .    imode - `INSERT_VALUES` or `ADD_VALUES`
6656f3c3dcfSJed Brown -    lvecs - the individual sequential vectors, NULL for any that are not needed
6666f3c3dcfSJed Brown 
6676f3c3dcfSJed Brown     Level: advanced
6686f3c3dcfSJed Brown 
669*dce8aebaSBarry Smith     Note:
670*dce8aebaSBarry Smith     This is a non-variadic alternative to `DMCompositeGather()`.
6716f3c3dcfSJed Brown 
672*dce8aebaSBarry Smith .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`,
673db781477SPatrick Sanan          `DMCompositeScatter()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`,
674db781477SPatrick Sanan          `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()`,
6756f3c3dcfSJed Brown @*/
676d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompositeGatherArray(DM dm, InsertMode imode, Vec gvec, Vec *lvecs)
677d71ae5a4SJacob Faibussowitsch {
6786f3c3dcfSJed Brown   struct DMCompositeLink *next;
6796f3c3dcfSJed Brown   DM_Composite           *com = (DM_Composite *)dm->data;
6806f3c3dcfSJed Brown   PetscInt                i;
68171b14b3eSStefano Zampini   PetscBool               flg;
6826f3c3dcfSJed Brown 
6836f3c3dcfSJed Brown   PetscFunctionBegin;
6846f3c3dcfSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
685064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(gvec, VEC_CLASSID, 3);
6869566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
6877a8be351SBarry Smith   PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
68848a46eb9SPierre Jolivet   if (!com->setup) PetscCall(DMSetUp(dm));
6896f3c3dcfSJed Brown 
6906f3c3dcfSJed Brown   /* loop over packed objects, handling one at at time */
6916f3c3dcfSJed Brown   for (next = com->next, i = 0; next; next = next->next, i++) {
6926f3c3dcfSJed Brown     if (lvecs[i]) {
6936f3c3dcfSJed Brown       PetscScalar *array;
6946f3c3dcfSJed Brown       Vec          global;
695064a246eSJacob Faibussowitsch       PetscValidHeaderSpecific(lvecs[i], VEC_CLASSID, 4);
6969566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalVector(next->dm, &global));
6979566063dSJacob Faibussowitsch       PetscCall(VecGetArray(gvec, &array));
6989566063dSJacob Faibussowitsch       PetscCall(VecPlaceArray(global, array + next->rstart));
6999566063dSJacob Faibussowitsch       PetscCall(DMLocalToGlobalBegin(next->dm, lvecs[i], imode, global));
7009566063dSJacob Faibussowitsch       PetscCall(DMLocalToGlobalEnd(next->dm, lvecs[i], imode, global));
7019566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(gvec, &array));
7029566063dSJacob Faibussowitsch       PetscCall(VecResetArray(global));
7039566063dSJacob Faibussowitsch       PetscCall(DMRestoreGlobalVector(next->dm, &global));
7046f3c3dcfSJed Brown     }
7056f3c3dcfSJed Brown   }
7066f3c3dcfSJed Brown   PetscFunctionReturn(0);
7076f3c3dcfSJed Brown }
7086f3c3dcfSJed Brown 
709f5f57ec0SBarry Smith /*@
710*dce8aebaSBarry Smith     DMCompositeAddDM - adds a `DM` vector to a `DMCOMPOSITE`
71147c6ae99SBarry Smith 
712d083f849SBarry Smith     Collective on dm
71347c6ae99SBarry Smith 
714d8d19677SJose E. Roman     Input Parameters:
715*dce8aebaSBarry Smith +    dmc - the  `DMCOMPOSITE` object
716*dce8aebaSBarry Smith -    dm - the `DM` object
71747c6ae99SBarry Smith 
71847c6ae99SBarry Smith     Level: advanced
71947c6ae99SBarry Smith 
720*dce8aebaSBarry Smith .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeGather()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`,
721db781477SPatrick Sanan          `DMCompositeScatter()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`,
722db781477SPatrick Sanan          `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()`
72347c6ae99SBarry Smith @*/
724d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompositeAddDM(DM dmc, DM dm)
725d71ae5a4SJacob Faibussowitsch {
72606ebdd98SJed Brown   PetscInt                n, nlocal;
72747c6ae99SBarry Smith   struct DMCompositeLink *mine, *next;
72806ebdd98SJed Brown   Vec                     global, local;
72947c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite *)dmc->data;
73071b14b3eSStefano Zampini   PetscBool               flg;
73147c6ae99SBarry Smith 
73247c6ae99SBarry Smith   PetscFunctionBegin;
73347c6ae99SBarry Smith   PetscValidHeaderSpecific(dmc, DM_CLASSID, 1);
73447c6ae99SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
7359566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dmc, DMCOMPOSITE, &flg));
7367a8be351SBarry Smith   PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
73747c6ae99SBarry Smith   next = com->next;
73828b400f6SJacob Faibussowitsch   PetscCheck(!com->setup, PetscObjectComm((PetscObject)dmc), PETSC_ERR_ARG_WRONGSTATE, "Cannot add a DM once you have used the DMComposite");
73947c6ae99SBarry Smith 
74047c6ae99SBarry Smith   /* create new link */
7419566063dSJacob Faibussowitsch   PetscCall(PetscNew(&mine));
7429566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)dm));
7439566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalVector(dm, &global));
7449566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(global, &n));
7459566063dSJacob Faibussowitsch   PetscCall(DMRestoreGlobalVector(dm, &global));
7469566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dm, &local));
7479566063dSJacob Faibussowitsch   PetscCall(VecGetSize(local, &nlocal));
7489566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dm, &local));
7498865f1eaSKarl Rupp 
75047c6ae99SBarry Smith   mine->n      = n;
75106ebdd98SJed Brown   mine->nlocal = nlocal;
75247c6ae99SBarry Smith   mine->dm     = dm;
7530298fd71SBarry Smith   mine->next   = NULL;
75447c6ae99SBarry Smith   com->n += n;
7557ac2b803SAlex Fikl   com->nghost += nlocal;
75647c6ae99SBarry Smith 
75747c6ae99SBarry Smith   /* add to end of list */
7588865f1eaSKarl Rupp   if (!next) com->next = mine;
7598865f1eaSKarl Rupp   else {
76047c6ae99SBarry Smith     while (next->next) next = next->next;
76147c6ae99SBarry Smith     next->next = mine;
76247c6ae99SBarry Smith   }
76347c6ae99SBarry Smith   com->nDM++;
76447c6ae99SBarry Smith   com->nmine++;
76547c6ae99SBarry Smith   PetscFunctionReturn(0);
76647c6ae99SBarry Smith }
76747c6ae99SBarry Smith 
7689804daf3SBarry Smith #include <petscdraw.h>
76926887b52SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer);
770d71ae5a4SJacob Faibussowitsch PetscErrorCode              VecView_DMComposite(Vec gvec, PetscViewer viewer)
771d71ae5a4SJacob Faibussowitsch {
77247c6ae99SBarry Smith   DM                      dm;
77347c6ae99SBarry Smith   struct DMCompositeLink *next;
77447c6ae99SBarry Smith   PetscBool               isdraw;
775cef07954SSatish Balay   DM_Composite           *com;
77647c6ae99SBarry Smith 
77747c6ae99SBarry Smith   PetscFunctionBegin;
7789566063dSJacob Faibussowitsch   PetscCall(VecGetDM(gvec, &dm));
7797a8be351SBarry Smith   PetscCheck(dm, PetscObjectComm((PetscObject)gvec), PETSC_ERR_ARG_WRONG, "Vector not generated from a DMComposite");
78047c6ae99SBarry Smith   com  = (DM_Composite *)dm->data;
78147c6ae99SBarry Smith   next = com->next;
78247c6ae99SBarry Smith 
7839566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
78447c6ae99SBarry Smith   if (!isdraw) {
78547c6ae99SBarry Smith     /* do I really want to call this? */
7869566063dSJacob Faibussowitsch     PetscCall(VecView_MPI(gvec, viewer));
78747c6ae99SBarry Smith   } else {
78847c6ae99SBarry Smith     PetscInt cnt = 0;
78947c6ae99SBarry Smith 
79047c6ae99SBarry Smith     /* loop over packed objects, handling one at at time */
79147c6ae99SBarry Smith     while (next) {
79247c6ae99SBarry Smith       Vec                vec;
793ca4278abSLisandro Dalcin       const PetscScalar *array;
79447c6ae99SBarry Smith       PetscInt           bs;
79547c6ae99SBarry Smith 
7969ae5db72SJed Brown       /* Should use VecGetSubVector() eventually, but would need to forward the DM for that to work */
7979566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalVector(next->dm, &vec));
7989566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(gvec, &array));
7999566063dSJacob Faibussowitsch       PetscCall(VecPlaceArray(vec, (PetscScalar *)array + next->rstart));
8009566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(gvec, &array));
8019566063dSJacob Faibussowitsch       PetscCall(VecView(vec, viewer));
8029566063dSJacob Faibussowitsch       PetscCall(VecResetArray(vec));
8039566063dSJacob Faibussowitsch       PetscCall(VecGetBlockSize(vec, &bs));
8049566063dSJacob Faibussowitsch       PetscCall(DMRestoreGlobalVector(next->dm, &vec));
8059566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawBaseAdd(viewer, bs));
80647c6ae99SBarry Smith       cnt += bs;
80747c6ae99SBarry Smith       next = next->next;
80847c6ae99SBarry Smith     }
8099566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawBaseAdd(viewer, -cnt));
81047c6ae99SBarry Smith   }
81147c6ae99SBarry Smith   PetscFunctionReturn(0);
81247c6ae99SBarry Smith }
81347c6ae99SBarry Smith 
814d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateGlobalVector_Composite(DM dm, Vec *gvec)
815d71ae5a4SJacob Faibussowitsch {
81647c6ae99SBarry Smith   DM_Composite *com = (DM_Composite *)dm->data;
81747c6ae99SBarry Smith 
81847c6ae99SBarry Smith   PetscFunctionBegin;
81947c6ae99SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8209566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(dm));
8219566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
8229566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), gvec));
8239566063dSJacob Faibussowitsch   PetscCall(VecSetType(*gvec, dm->vectype));
8249566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(*gvec, com->n, com->N));
8259566063dSJacob Faibussowitsch   PetscCall(VecSetDM(*gvec, dm));
8269566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*gvec, VECOP_VIEW, (void (*)(void))VecView_DMComposite));
82747c6ae99SBarry Smith   PetscFunctionReturn(0);
82847c6ae99SBarry Smith }
82947c6ae99SBarry Smith 
830d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLocalVector_Composite(DM dm, Vec *lvec)
831d71ae5a4SJacob Faibussowitsch {
83247c6ae99SBarry Smith   DM_Composite *com = (DM_Composite *)dm->data;
83347c6ae99SBarry Smith 
83447c6ae99SBarry Smith   PetscFunctionBegin;
83547c6ae99SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
83647c6ae99SBarry Smith   if (!com->setup) {
8379566063dSJacob Faibussowitsch     PetscCall(DMSetFromOptions(dm));
8389566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
83947c6ae99SBarry Smith   }
8409566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, lvec));
8419566063dSJacob Faibussowitsch   PetscCall(VecSetType(*lvec, dm->vectype));
8429566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(*lvec, com->nghost, PETSC_DECIDE));
8439566063dSJacob Faibussowitsch   PetscCall(VecSetDM(*lvec, dm));
84447c6ae99SBarry Smith   PetscFunctionReturn(0);
84547c6ae99SBarry Smith }
84647c6ae99SBarry Smith 
84747c6ae99SBarry Smith /*@C
848*dce8aebaSBarry Smith     DMCompositeGetISLocalToGlobalMappings - gets an `ISLocalToGlobalMapping` for each `DM` in the `DMCOMPOSITE`, maps to the composite global space
84947c6ae99SBarry Smith 
850*dce8aebaSBarry Smith     Collective on dm
85147c6ae99SBarry Smith 
85247c6ae99SBarry Smith     Input Parameter:
853*dce8aebaSBarry Smith .    dm - the `DMCOMPOSITE` object
85447c6ae99SBarry Smith 
85547c6ae99SBarry Smith     Output Parameters:
8569ae5db72SJed Brown .    ltogs - the individual mappings for each packed vector. Note that this includes
857*dce8aebaSBarry Smith            all the ghost points that individual ghosted `DMDA` may have.
85847c6ae99SBarry Smith 
85947c6ae99SBarry Smith     Level: advanced
86047c6ae99SBarry Smith 
861*dce8aebaSBarry Smith     Note:
862*dce8aebaSBarry Smith     Each entry of ltogs should be destroyed with `ISLocalToGlobalMappingDestroy()`, the ltogs array should be freed with `PetscFree()`.
86347c6ae99SBarry Smith 
864*dce8aebaSBarry Smith     Fortran Note:
865f5f57ec0SBarry Smith     Not available from Fortran
866f5f57ec0SBarry Smith 
867*dce8aebaSBarry Smith .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`,
868db781477SPatrick Sanan          `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetAccess()`, `DMCompositeScatter()`,
869c2e3fba1SPatrick Sanan          `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()`
87047c6ae99SBarry Smith @*/
871d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompositeGetISLocalToGlobalMappings(DM dm, ISLocalToGlobalMapping **ltogs)
872d71ae5a4SJacob Faibussowitsch {
87347c6ae99SBarry Smith   PetscInt                i, *idx, n, cnt;
87447c6ae99SBarry Smith   struct DMCompositeLink *next;
87547c6ae99SBarry Smith   PetscMPIInt             rank;
87647c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite *)dm->data;
87771b14b3eSStefano Zampini   PetscBool               flg;
87847c6ae99SBarry Smith 
87947c6ae99SBarry Smith   PetscFunctionBegin;
88047c6ae99SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8819566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
8827a8be351SBarry Smith   PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
8839566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
8849566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(com->nDM, ltogs));
88547c6ae99SBarry Smith   next = com->next;
8869566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
88747c6ae99SBarry Smith 
88847c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
88947c6ae99SBarry Smith   cnt = 0;
89047c6ae99SBarry Smith   while (next) {
8916eb61c8cSJed Brown     ISLocalToGlobalMapping ltog;
8926eb61c8cSJed Brown     PetscMPIInt            size;
89386994e45SJed Brown     const PetscInt        *suboff, *indices;
8946eb61c8cSJed Brown     Vec                    global;
89547c6ae99SBarry Smith 
8966eb61c8cSJed Brown     /* Get sub-DM global indices for each local dof */
8979566063dSJacob Faibussowitsch     PetscCall(DMGetLocalToGlobalMapping(next->dm, &ltog));
8989566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(ltog, &n));
8999566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetIndices(ltog, &indices));
9009566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n, &idx));
90147c6ae99SBarry Smith 
9026eb61c8cSJed Brown     /* Get the offsets for the sub-DM global vector */
9039566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(next->dm, &global));
9049566063dSJacob Faibussowitsch     PetscCall(VecGetOwnershipRanges(global, &suboff));
9059566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)global), &size));
9066eb61c8cSJed Brown 
9076eb61c8cSJed Brown     /* Shift the sub-DM definition of the global space to the composite global space */
9086eb61c8cSJed Brown     for (i = 0; i < n; i++) {
90986994e45SJed Brown       PetscInt subi = indices[i], lo = 0, hi = size, t;
910e333b035SStefano Zampini       /* There's no consensus on what a negative index means,
911e333b035SStefano Zampini          except for skipping when setting the values in vectors and matrices */
9129371c9d4SSatish Balay       if (subi < 0) {
9139371c9d4SSatish Balay         idx[i] = subi - next->grstarts[rank];
9149371c9d4SSatish Balay         continue;
9159371c9d4SSatish Balay       }
9166eb61c8cSJed Brown       /* Binary search to find which rank owns subi */
9176eb61c8cSJed Brown       while (hi - lo > 1) {
9186eb61c8cSJed Brown         t = lo + (hi - lo) / 2;
9196eb61c8cSJed Brown         if (suboff[t] > subi) hi = t;
9206eb61c8cSJed Brown         else lo = t;
9216eb61c8cSJed Brown       }
9226eb61c8cSJed Brown       idx[i] = subi - suboff[lo] + next->grstarts[lo];
9236eb61c8cSJed Brown     }
9249566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreIndices(ltog, &indices));
9259566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), 1, n, idx, PETSC_OWN_POINTER, &(*ltogs)[cnt]));
9269566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(next->dm, &global));
92747c6ae99SBarry Smith     next = next->next;
92847c6ae99SBarry Smith     cnt++;
92947c6ae99SBarry Smith   }
93047c6ae99SBarry Smith   PetscFunctionReturn(0);
93147c6ae99SBarry Smith }
93247c6ae99SBarry Smith 
93387c85e80SJed Brown /*@C
9349ae5db72SJed Brown    DMCompositeGetLocalISs - Gets index sets for each component of a composite local vector
93587c85e80SJed Brown 
93687c85e80SJed Brown    Not Collective
93787c85e80SJed Brown 
9384165533cSJose E. Roman    Input Parameter:
939*dce8aebaSBarry Smith . dm - the `DMCOMPOSITE`
94087c85e80SJed Brown 
9414165533cSJose E. Roman    Output Parameter:
942*dce8aebaSBarry Smith . is - array of serial index sets for each each component of the `DMCOMPOSITE`
94387c85e80SJed Brown 
94487c85e80SJed Brown    Level: intermediate
94587c85e80SJed Brown 
94687c85e80SJed Brown    Notes:
94787c85e80SJed Brown    At present, a composite local vector does not normally exist.  This function is used to provide index sets for
948*dce8aebaSBarry Smith    `MatGetLocalSubMatrix()`.  In the future, the scatters for each entry in the `DMCOMPOSITE` may be be merged into a single
9499ae5db72SJed Brown    scatter to a composite local vector.  The user should not typically need to know which is being done.
95087c85e80SJed Brown 
951*dce8aebaSBarry Smith    To get the composite global indices at all local points (including ghosts), use `DMCompositeGetISLocalToGlobalMappings()`.
95287c85e80SJed Brown 
953*dce8aebaSBarry Smith    To get index sets for pieces of the composite global vector, use `DMCompositeGetGlobalISs()`.
95487c85e80SJed Brown 
955*dce8aebaSBarry Smith    Each returned `IS` should be destroyed with `ISDestroy()`, the array should be freed with `PetscFree()`.
95687c85e80SJed Brown 
957*dce8aebaSBarry Smith    Fortran Note:
958f5f57ec0SBarry Smith    Not available from Fortran
959f5f57ec0SBarry Smith 
960*dce8aebaSBarry Smith .seealso: `DMCOMPOSITE`, `DM`, `DMCompositeGetGlobalISs()`, `DMCompositeGetISLocalToGlobalMappings()`, `MatGetLocalSubMatrix()`, `MatCreateLocalRef()`
96187c85e80SJed Brown @*/
962d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompositeGetLocalISs(DM dm, IS **is)
963d71ae5a4SJacob Faibussowitsch {
96487c85e80SJed Brown   DM_Composite           *com = (DM_Composite *)dm->data;
96587c85e80SJed Brown   struct DMCompositeLink *link;
96687c85e80SJed Brown   PetscInt                cnt, start;
96771b14b3eSStefano Zampini   PetscBool               flg;
96887c85e80SJed Brown 
96987c85e80SJed Brown   PetscFunctionBegin;
97087c85e80SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
97187c85e80SJed Brown   PetscValidPointer(is, 2);
9729566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
9737a8be351SBarry Smith   PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
9749566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(com->nmine, is));
97506ebdd98SJed Brown   for (cnt = 0, start = 0, link = com->next; link; start += link->nlocal, cnt++, link = link->next) {
976520db06cSJed Brown     PetscInt bs;
9779566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, link->nlocal, start, 1, &(*is)[cnt]));
9789566063dSJacob Faibussowitsch     PetscCall(DMGetBlockSize(link->dm, &bs));
9799566063dSJacob Faibussowitsch     PetscCall(ISSetBlockSize((*is)[cnt], bs));
980520db06cSJed Brown   }
98187c85e80SJed Brown   PetscFunctionReturn(0);
98287c85e80SJed Brown }
98387c85e80SJed Brown 
98447c6ae99SBarry Smith /*@C
985*dce8aebaSBarry Smith     DMCompositeGetGlobalISs - Gets the index sets for each composed object in a `DMCOMPOSITE`
98647c6ae99SBarry Smith 
987d083f849SBarry Smith     Collective on dm
98847c6ae99SBarry Smith 
98947c6ae99SBarry Smith     Input Parameter:
990*dce8aebaSBarry Smith .    dm - the `DMCOMPOSITE` object
99147c6ae99SBarry Smith 
99247c6ae99SBarry Smith     Output Parameters:
99347c6ae99SBarry Smith .    is - the array of index sets
99447c6ae99SBarry Smith 
99547c6ae99SBarry Smith     Level: advanced
99647c6ae99SBarry Smith 
99747c6ae99SBarry Smith     Notes:
998*dce8aebaSBarry Smith        The is entries should be destroyed with `ISDestroy()`, the is array should be freed with `PetscFree()`
99947c6ae99SBarry Smith 
100047c6ae99SBarry Smith        These could be used to extract a subset of vector entries for a "multi-physics" preconditioner
100147c6ae99SBarry Smith 
1002*dce8aebaSBarry Smith        Use `DMCompositeGetLocalISs()` for index sets in the packed local numbering, and
1003*dce8aebaSBarry Smith        `DMCompositeGetISLocalToGlobalMappings()` for to map local sub-`DM` (including ghost) indices to packed global
10046eb61c8cSJed Brown        indices.
100547c6ae99SBarry Smith 
1006*dce8aebaSBarry Smith     Fortran Note:
1007*dce8aebaSBarry Smith     The output argument 'is' must be an allocated array of sufficient length, which can be learned using `DMCompositeGetNumberDM()`.
1008f3cb0f7eSJed Brown 
1009*dce8aebaSBarry Smith .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`,
1010db781477SPatrick Sanan          `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetAccess()`, `DMCompositeScatter()`,
1011c2e3fba1SPatrick Sanan          `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()`
101247c6ae99SBarry Smith @*/
1013d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompositeGetGlobalISs(DM dm, IS *is[])
1014d71ae5a4SJacob Faibussowitsch {
101566bb578eSMark Adams   PetscInt                cnt = 0;
101647c6ae99SBarry Smith   struct DMCompositeLink *next;
101747c6ae99SBarry Smith   PetscMPIInt             rank;
101847c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite *)dm->data;
101971b14b3eSStefano Zampini   PetscBool               flg;
102047c6ae99SBarry Smith 
102147c6ae99SBarry Smith   PetscFunctionBegin;
102247c6ae99SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10239566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
10247a8be351SBarry Smith   PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
10257a8be351SBarry Smith   PetscCheck(dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Must call DMSetUp() before");
10269566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(com->nDM, is));
102747c6ae99SBarry Smith   next = com->next;
10289566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
102947c6ae99SBarry Smith 
103047c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
103147c6ae99SBarry Smith   while (next) {
1032e5e52638SMatthew G. Knepley     PetscDS prob;
1033e5e52638SMatthew G. Knepley 
10349566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)dm), next->n, next->grstart, 1, &(*is)[cnt]));
10359566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dm, &prob));
1036e5e52638SMatthew G. Knepley     if (prob) {
103765c226d8SMatthew G. Knepley       MatNullSpace space;
103865c226d8SMatthew G. Knepley       Mat          pmat;
10390f21e855SMatthew G. Knepley       PetscObject  disc;
10400f21e855SMatthew G. Knepley       PetscInt     Nf;
104165c226d8SMatthew G. Knepley 
10429566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(prob, &Nf));
1043f24dd8d2SMatthew G. Knepley       if (cnt < Nf) {
10449566063dSJacob Faibussowitsch         PetscCall(PetscDSGetDiscretization(prob, cnt, &disc));
10459566063dSJacob Faibussowitsch         PetscCall(PetscObjectQuery(disc, "nullspace", (PetscObject *)&space));
10469566063dSJacob Faibussowitsch         if (space) PetscCall(PetscObjectCompose((PetscObject)(*is)[cnt], "nullspace", (PetscObject)space));
10479566063dSJacob Faibussowitsch         PetscCall(PetscObjectQuery(disc, "nearnullspace", (PetscObject *)&space));
10489566063dSJacob Faibussowitsch         if (space) PetscCall(PetscObjectCompose((PetscObject)(*is)[cnt], "nearnullspace", (PetscObject)space));
10499566063dSJacob Faibussowitsch         PetscCall(PetscObjectQuery(disc, "pmat", (PetscObject *)&pmat));
10509566063dSJacob Faibussowitsch         if (pmat) PetscCall(PetscObjectCompose((PetscObject)(*is)[cnt], "pmat", (PetscObject)pmat));
105165c226d8SMatthew G. Knepley       }
1052f24dd8d2SMatthew G. Knepley     }
105347c6ae99SBarry Smith     cnt++;
105447c6ae99SBarry Smith     next = next->next;
105547c6ae99SBarry Smith   }
105647c6ae99SBarry Smith   PetscFunctionReturn(0);
105747c6ae99SBarry Smith }
105847c6ae99SBarry Smith 
1059d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateFieldIS_Composite(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields)
1060d71ae5a4SJacob Faibussowitsch {
10614d343eeaSMatthew G Knepley   PetscInt nDM;
10624d343eeaSMatthew G Knepley   DM      *dms;
10634d343eeaSMatthew G Knepley   PetscInt i;
10644d343eeaSMatthew G Knepley 
10654d343eeaSMatthew G Knepley   PetscFunctionBegin;
10669566063dSJacob Faibussowitsch   PetscCall(DMCompositeGetNumberDM(dm, &nDM));
10678865f1eaSKarl Rupp   if (numFields) *numFields = nDM;
10689566063dSJacob Faibussowitsch   PetscCall(DMCompositeGetGlobalISs(dm, fields));
10694d343eeaSMatthew G Knepley   if (fieldNames) {
10709566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nDM, &dms));
10719566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nDM, fieldNames));
10729566063dSJacob Faibussowitsch     PetscCall(DMCompositeGetEntriesArray(dm, dms));
10734d343eeaSMatthew G Knepley     for (i = 0; i < nDM; i++) {
10744d343eeaSMatthew G Knepley       char        buf[256];
10754d343eeaSMatthew G Knepley       const char *splitname;
10764d343eeaSMatthew G Knepley 
10774d343eeaSMatthew G Knepley       /* Split naming precedence: object name, prefix, number */
10784d343eeaSMatthew G Knepley       splitname = ((PetscObject)dm)->name;
10794d343eeaSMatthew G Knepley       if (!splitname) {
10809566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dms[i], &splitname));
10814d343eeaSMatthew G Knepley         if (splitname) {
10824d343eeaSMatthew G Knepley           size_t len;
10839566063dSJacob Faibussowitsch           PetscCall(PetscStrncpy(buf, splitname, sizeof(buf)));
10848caf3d72SBarry Smith           buf[sizeof(buf) - 1] = 0;
10859566063dSJacob Faibussowitsch           PetscCall(PetscStrlen(buf, &len));
10864d343eeaSMatthew G Knepley           if (buf[len - 1] == '_') buf[len - 1] = 0; /* Remove trailing underscore if it was used */
10874d343eeaSMatthew G Knepley           splitname = buf;
10884d343eeaSMatthew G Knepley         }
10894d343eeaSMatthew G Knepley       }
10904d343eeaSMatthew G Knepley       if (!splitname) {
109163a3b9bcSJacob Faibussowitsch         PetscCall(PetscSNPrintf(buf, sizeof(buf), "%" PetscInt_FMT, i));
10924d343eeaSMatthew G Knepley         splitname = buf;
10934d343eeaSMatthew G Knepley       }
10949566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(splitname, &(*fieldNames)[i]));
10954d343eeaSMatthew G Knepley     }
10969566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
10974d343eeaSMatthew G Knepley   }
10984d343eeaSMatthew G Knepley   PetscFunctionReturn(0);
10994d343eeaSMatthew G Knepley }
11004d343eeaSMatthew G Knepley 
1101e7c4fc90SDmitry Karpeev /*
1102e7c4fc90SDmitry Karpeev  This could take over from DMCreateFieldIS(), as it is more general,
11030298fd71SBarry Smith  making DMCreateFieldIS() a special case -- calling with dmlist == NULL;
1104e7c4fc90SDmitry Karpeev  At this point it's probably best to be less intrusive, however.
1105e7c4fc90SDmitry Karpeev  */
1106d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateFieldDecomposition_Composite(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
1107d71ae5a4SJacob Faibussowitsch {
1108e7c4fc90SDmitry Karpeev   PetscInt nDM;
1109e7c4fc90SDmitry Karpeev   PetscInt i;
1110e7c4fc90SDmitry Karpeev 
1111e7c4fc90SDmitry Karpeev   PetscFunctionBegin;
11129566063dSJacob Faibussowitsch   PetscCall(DMCreateFieldIS_Composite(dm, len, namelist, islist));
1113e7c4fc90SDmitry Karpeev   if (dmlist) {
11149566063dSJacob Faibussowitsch     PetscCall(DMCompositeGetNumberDM(dm, &nDM));
11159566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nDM, dmlist));
11169566063dSJacob Faibussowitsch     PetscCall(DMCompositeGetEntriesArray(dm, *dmlist));
111748a46eb9SPierre Jolivet     for (i = 0; i < nDM; i++) PetscCall(PetscObjectReference((PetscObject)((*dmlist)[i])));
1118e7c4fc90SDmitry Karpeev   }
1119e7c4fc90SDmitry Karpeev   PetscFunctionReturn(0);
1120e7c4fc90SDmitry Karpeev }
1121e7c4fc90SDmitry Karpeev 
112247c6ae99SBarry Smith /* -------------------------------------------------------------------------------------*/
112347c6ae99SBarry Smith /*@C
1124*dce8aebaSBarry Smith     DMCompositeGetLocalVectors - Gets local vectors for each part of a `DMCOMPOSITE`
1125*dce8aebaSBarry Smith        Use `DMCompositeRestoreLocalVectors()` to return them.
112647c6ae99SBarry Smith 
112747c6ae99SBarry Smith     Not Collective
112847c6ae99SBarry Smith 
112947c6ae99SBarry Smith     Input Parameter:
1130*dce8aebaSBarry Smith .    dm - the `DMCOMPOSITE` object
113147c6ae99SBarry Smith 
113247c6ae99SBarry Smith     Output Parameter:
11339ae5db72SJed Brown .   Vec ... - the individual sequential Vecs
113447c6ae99SBarry Smith 
113547c6ae99SBarry Smith     Level: advanced
113647c6ae99SBarry Smith 
1137*dce8aebaSBarry Smith     Fortran Note:
1138f5f57ec0SBarry Smith     Not available from Fortran
1139f5f57ec0SBarry Smith 
1140*dce8aebaSBarry Smith .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`,
1141db781477SPatrick Sanan          `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`,
1142db781477SPatrick Sanan          `DMCompositeRestoreLocalVectors()`, `DMCompositeScatter()`, `DMCompositeGetEntries()`
114347c6ae99SBarry Smith @*/
1144d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompositeGetLocalVectors(DM dm, ...)
1145d71ae5a4SJacob Faibussowitsch {
114647c6ae99SBarry Smith   va_list                 Argp;
114747c6ae99SBarry Smith   struct DMCompositeLink *next;
114847c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite *)dm->data;
114971b14b3eSStefano Zampini   PetscBool               flg;
115047c6ae99SBarry Smith 
115147c6ae99SBarry Smith   PetscFunctionBegin;
115247c6ae99SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
11539566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
11547a8be351SBarry Smith   PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
115547c6ae99SBarry Smith   next = com->next;
115647c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
115747c6ae99SBarry Smith   va_start(Argp, dm);
115847c6ae99SBarry Smith   while (next) {
115947c6ae99SBarry Smith     Vec *vec;
116047c6ae99SBarry Smith     vec = va_arg(Argp, Vec *);
11619566063dSJacob Faibussowitsch     if (vec) PetscCall(DMGetLocalVector(next->dm, vec));
116247c6ae99SBarry Smith     next = next->next;
116347c6ae99SBarry Smith   }
116447c6ae99SBarry Smith   va_end(Argp);
116547c6ae99SBarry Smith   PetscFunctionReturn(0);
116647c6ae99SBarry Smith }
116747c6ae99SBarry Smith 
116847c6ae99SBarry Smith /*@C
1169*dce8aebaSBarry Smith     DMCompositeRestoreLocalVectors - Restores local vectors for each part of a `DMCOMPOSITE`
117047c6ae99SBarry Smith 
117147c6ae99SBarry Smith     Not Collective
117247c6ae99SBarry Smith 
117347c6ae99SBarry Smith     Input Parameter:
1174*dce8aebaSBarry Smith .    dm - the `DMCOMPOSITE` object
117547c6ae99SBarry Smith 
117647c6ae99SBarry Smith     Output Parameter:
1177*dce8aebaSBarry Smith .   Vec ... - the individual sequential `Vec`
117847c6ae99SBarry Smith 
117947c6ae99SBarry Smith     Level: advanced
118047c6ae99SBarry Smith 
1181*dce8aebaSBarry Smith     Fortran Note:
1182f5f57ec0SBarry Smith     Not available from Fortran
1183f5f57ec0SBarry Smith 
1184*dce8aebaSBarry Smith .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`,
1185db781477SPatrick Sanan          `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`,
1186db781477SPatrick Sanan          `DMCompositeGetLocalVectors()`, `DMCompositeScatter()`, `DMCompositeGetEntries()`
118747c6ae99SBarry Smith @*/
1188d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompositeRestoreLocalVectors(DM dm, ...)
1189d71ae5a4SJacob Faibussowitsch {
119047c6ae99SBarry Smith   va_list                 Argp;
119147c6ae99SBarry Smith   struct DMCompositeLink *next;
119247c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite *)dm->data;
119371b14b3eSStefano Zampini   PetscBool               flg;
119447c6ae99SBarry Smith 
119547c6ae99SBarry Smith   PetscFunctionBegin;
119647c6ae99SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
11979566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
11987a8be351SBarry Smith   PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
119947c6ae99SBarry Smith   next = com->next;
120047c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
120147c6ae99SBarry Smith   va_start(Argp, dm);
120247c6ae99SBarry Smith   while (next) {
120347c6ae99SBarry Smith     Vec *vec;
120447c6ae99SBarry Smith     vec = va_arg(Argp, Vec *);
12059566063dSJacob Faibussowitsch     if (vec) PetscCall(DMRestoreLocalVector(next->dm, vec));
120647c6ae99SBarry Smith     next = next->next;
120747c6ae99SBarry Smith   }
120847c6ae99SBarry Smith   va_end(Argp);
120947c6ae99SBarry Smith   PetscFunctionReturn(0);
121047c6ae99SBarry Smith }
121147c6ae99SBarry Smith 
121247c6ae99SBarry Smith /* -------------------------------------------------------------------------------------*/
121347c6ae99SBarry Smith /*@C
1214*dce8aebaSBarry Smith     DMCompositeGetEntries - Gets the `DM` for each entry in a `DMCOMPOSITE`.
121547c6ae99SBarry Smith 
121647c6ae99SBarry Smith     Not Collective
121747c6ae99SBarry Smith 
121847c6ae99SBarry Smith     Input Parameter:
1219*dce8aebaSBarry Smith .    dm - the `DMCOMPOSITE` object
122047c6ae99SBarry Smith 
122147c6ae99SBarry Smith     Output Parameter:
1222*dce8aebaSBarry Smith .   DM ... - the individual entries `DM`
122347c6ae99SBarry Smith 
122447c6ae99SBarry Smith     Level: advanced
122547c6ae99SBarry Smith 
1226*dce8aebaSBarry Smith     Fortran Note:
1227*dce8aebaSBarry Smith     Available as `DMCompositeGetEntries()` for one output `DM`, DMCompositeGetEntries2() for 2, etc
1228f5f57ec0SBarry Smith 
1229*dce8aebaSBarry Smith .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`, `DMCompositeGetEntriesArray()`
1230db781477SPatrick Sanan          `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`,
1231db781477SPatrick Sanan          `DMCompositeRestoreLocalVectors()`, `DMCompositeGetLocalVectors()`, `DMCompositeScatter()`,
1232db781477SPatrick Sanan          `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`
123347c6ae99SBarry Smith @*/
1234d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompositeGetEntries(DM dm, ...)
1235d71ae5a4SJacob Faibussowitsch {
123647c6ae99SBarry Smith   va_list                 Argp;
123747c6ae99SBarry Smith   struct DMCompositeLink *next;
123847c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite *)dm->data;
123971b14b3eSStefano Zampini   PetscBool               flg;
124047c6ae99SBarry Smith 
124147c6ae99SBarry Smith   PetscFunctionBegin;
124247c6ae99SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
12439566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
12447a8be351SBarry Smith   PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
124547c6ae99SBarry Smith   next = com->next;
124647c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
124747c6ae99SBarry Smith   va_start(Argp, dm);
124847c6ae99SBarry Smith   while (next) {
124947c6ae99SBarry Smith     DM *dmn;
125047c6ae99SBarry Smith     dmn = va_arg(Argp, DM *);
12519ae5db72SJed Brown     if (dmn) *dmn = next->dm;
125247c6ae99SBarry Smith     next = next->next;
125347c6ae99SBarry Smith   }
125447c6ae99SBarry Smith   va_end(Argp);
125547c6ae99SBarry Smith   PetscFunctionReturn(0);
125647c6ae99SBarry Smith }
125747c6ae99SBarry Smith 
1258dbab29e1SMark F. Adams /*@C
1259*dce8aebaSBarry Smith     DMCompositeGetEntriesArray - Gets the DM for each entry in a `DMCOMPOSITE`
12602fa5ba8aSJed Brown 
12612fa5ba8aSJed Brown     Not Collective
12622fa5ba8aSJed Brown 
12632fa5ba8aSJed Brown     Input Parameter:
1264*dce8aebaSBarry Smith .    dm - the `DMCOMPOSITE` object
1265907376e6SBarry Smith 
1266907376e6SBarry Smith     Output Parameter:
1267*dce8aebaSBarry Smith .    dms - array of sufficient length (see `DMCompositeGetNumberDM()`) to hold the individual `DM`
12682fa5ba8aSJed Brown 
12692fa5ba8aSJed Brown     Level: advanced
12702fa5ba8aSJed Brown 
1271*dce8aebaSBarry Smith .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`, `DMCompositeGetEntries()`
1272db781477SPatrick Sanan          `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`,
1273db781477SPatrick Sanan          `DMCompositeRestoreLocalVectors()`, `DMCompositeGetLocalVectors()`, `DMCompositeScatter()`,
1274db781477SPatrick Sanan          `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`
12752fa5ba8aSJed Brown @*/
1276d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompositeGetEntriesArray(DM dm, DM dms[])
1277d71ae5a4SJacob Faibussowitsch {
12782fa5ba8aSJed Brown   struct DMCompositeLink *next;
12792fa5ba8aSJed Brown   DM_Composite           *com = (DM_Composite *)dm->data;
12802fa5ba8aSJed Brown   PetscInt                i;
128171b14b3eSStefano Zampini   PetscBool               flg;
12822fa5ba8aSJed Brown 
12832fa5ba8aSJed Brown   PetscFunctionBegin;
12842fa5ba8aSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
12859566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
12867a8be351SBarry Smith   PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
12872fa5ba8aSJed Brown   /* loop over packed objects, handling one at at time */
12882fa5ba8aSJed Brown   for (next = com->next, i = 0; next; next = next->next, i++) dms[i] = next->dm;
12892fa5ba8aSJed Brown   PetscFunctionReturn(0);
12902fa5ba8aSJed Brown }
12912fa5ba8aSJed Brown 
1292e10fd815SStefano Zampini typedef struct {
1293e10fd815SStefano Zampini   DM           dm;
1294e10fd815SStefano Zampini   PetscViewer *subv;
1295e10fd815SStefano Zampini   Vec         *vecs;
1296e10fd815SStefano Zampini } GLVisViewerCtx;
1297e10fd815SStefano Zampini 
1298d71ae5a4SJacob Faibussowitsch static PetscErrorCode DestroyGLVisViewerCtx_Private(void *vctx)
1299d71ae5a4SJacob Faibussowitsch {
1300e10fd815SStefano Zampini   GLVisViewerCtx *ctx = (GLVisViewerCtx *)vctx;
1301e10fd815SStefano Zampini   PetscInt        i, n;
1302e10fd815SStefano Zampini 
1303e10fd815SStefano Zampini   PetscFunctionBegin;
13049566063dSJacob Faibussowitsch   PetscCall(DMCompositeGetNumberDM(ctx->dm, &n));
130548a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall(PetscViewerDestroy(&ctx->subv[i]));
13069566063dSJacob Faibussowitsch   PetscCall(PetscFree2(ctx->subv, ctx->vecs));
13079566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&ctx->dm));
13089566063dSJacob Faibussowitsch   PetscCall(PetscFree(ctx));
1309e10fd815SStefano Zampini   PetscFunctionReturn(0);
1310e10fd815SStefano Zampini }
1311e10fd815SStefano Zampini 
1312d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCompositeSampleGLVisFields_Private(PetscObject oX, PetscInt nf, PetscObject oXfield[], void *vctx)
1313d71ae5a4SJacob Faibussowitsch {
1314e10fd815SStefano Zampini   Vec             X   = (Vec)oX;
1315e10fd815SStefano Zampini   GLVisViewerCtx *ctx = (GLVisViewerCtx *)vctx;
1316e10fd815SStefano Zampini   PetscInt        i, n, cumf;
1317e10fd815SStefano Zampini 
1318e10fd815SStefano Zampini   PetscFunctionBegin;
13199566063dSJacob Faibussowitsch   PetscCall(DMCompositeGetNumberDM(ctx->dm, &n));
13209566063dSJacob Faibussowitsch   PetscCall(DMCompositeGetAccessArray(ctx->dm, X, n, NULL, ctx->vecs));
1321e10fd815SStefano Zampini   for (i = 0, cumf = 0; i < n; i++) {
1322e10fd815SStefano Zampini     PetscErrorCode (*g2l)(PetscObject, PetscInt, PetscObject[], void *);
1323e10fd815SStefano Zampini     void    *fctx;
1324e10fd815SStefano Zampini     PetscInt nfi;
1325e10fd815SStefano Zampini 
13269566063dSJacob Faibussowitsch     PetscCall(PetscViewerGLVisGetFields_Private(ctx->subv[i], &nfi, NULL, NULL, &g2l, NULL, &fctx));
1327e10fd815SStefano Zampini     if (!nfi) continue;
13281baa6e33SBarry Smith     if (g2l) PetscCall((*g2l)((PetscObject)ctx->vecs[i], nfi, oXfield + cumf, fctx));
13291baa6e33SBarry Smith     else PetscCall(VecCopy(ctx->vecs[i], (Vec)(oXfield[cumf])));
1330e10fd815SStefano Zampini     cumf += nfi;
1331e10fd815SStefano Zampini   }
13329566063dSJacob Faibussowitsch   PetscCall(DMCompositeRestoreAccessArray(ctx->dm, X, n, NULL, ctx->vecs));
1333e10fd815SStefano Zampini   PetscFunctionReturn(0);
1334e10fd815SStefano Zampini }
1335e10fd815SStefano Zampini 
1336d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetUpGLVisViewer_Composite(PetscObject odm, PetscViewer viewer)
1337d71ae5a4SJacob Faibussowitsch {
1338e10fd815SStefano Zampini   DM              dm = (DM)odm, *dms;
1339e10fd815SStefano Zampini   Vec            *Ufds;
1340e10fd815SStefano Zampini   GLVisViewerCtx *ctx;
1341e10fd815SStefano Zampini   PetscInt        i, n, tnf, *sdim;
1342e10fd815SStefano Zampini   char          **fecs;
1343e10fd815SStefano Zampini 
1344e10fd815SStefano Zampini   PetscFunctionBegin;
13459566063dSJacob Faibussowitsch   PetscCall(PetscNew(&ctx));
13469566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)dm));
1347e10fd815SStefano Zampini   ctx->dm = dm;
13489566063dSJacob Faibussowitsch   PetscCall(DMCompositeGetNumberDM(dm, &n));
13499566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n, &dms));
13509566063dSJacob Faibussowitsch   PetscCall(DMCompositeGetEntriesArray(dm, dms));
13519566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(n, &ctx->subv, n, &ctx->vecs));
1352e10fd815SStefano Zampini   for (i = 0, tnf = 0; i < n; i++) {
1353e10fd815SStefano Zampini     PetscInt nf;
1354e10fd815SStefano Zampini 
13559566063dSJacob Faibussowitsch     PetscCall(PetscViewerCreate(PetscObjectComm(odm), &ctx->subv[i]));
13569566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetType(ctx->subv[i], PETSCVIEWERGLVIS));
13579566063dSJacob Faibussowitsch     PetscCall(PetscViewerGLVisSetDM_Private(ctx->subv[i], (PetscObject)dms[i]));
13589566063dSJacob Faibussowitsch     PetscCall(PetscViewerGLVisGetFields_Private(ctx->subv[i], &nf, NULL, NULL, NULL, NULL, NULL));
1359e10fd815SStefano Zampini     tnf += nf;
1360e10fd815SStefano Zampini   }
13619566063dSJacob Faibussowitsch   PetscCall(PetscFree(dms));
13629566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(tnf, &fecs, tnf, &sdim, tnf, &Ufds));
1363e10fd815SStefano Zampini   for (i = 0, tnf = 0; i < n; i++) {
1364e10fd815SStefano Zampini     PetscInt    *sd, nf, f;
1365e10fd815SStefano Zampini     const char **fec;
1366e10fd815SStefano Zampini     Vec         *Uf;
1367e10fd815SStefano Zampini 
13689566063dSJacob Faibussowitsch     PetscCall(PetscViewerGLVisGetFields_Private(ctx->subv[i], &nf, &fec, &sd, NULL, (PetscObject **)&Uf, NULL));
1369e10fd815SStefano Zampini     for (f = 0; f < nf; f++) {
13709566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(fec[f], &fecs[tnf + f]));
1371e10fd815SStefano Zampini       Ufds[tnf + f] = Uf[f];
1372e10fd815SStefano Zampini       sdim[tnf + f] = sd[f];
1373e10fd815SStefano Zampini     }
1374e10fd815SStefano Zampini     tnf += nf;
1375e10fd815SStefano Zampini   }
13769566063dSJacob Faibussowitsch   PetscCall(PetscViewerGLVisSetFields(viewer, tnf, (const char **)fecs, sdim, DMCompositeSampleGLVisFields_Private, (PetscObject *)Ufds, ctx, DestroyGLVisViewerCtx_Private));
137748a46eb9SPierre Jolivet   for (i = 0; i < tnf; i++) PetscCall(PetscFree(fecs[i]));
13789566063dSJacob Faibussowitsch   PetscCall(PetscFree3(fecs, sdim, Ufds));
1379e10fd815SStefano Zampini   PetscFunctionReturn(0);
1380e10fd815SStefano Zampini }
1381e10fd815SStefano Zampini 
1382d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRefine_Composite(DM dmi, MPI_Comm comm, DM *fine)
1383d71ae5a4SJacob Faibussowitsch {
138447c6ae99SBarry Smith   struct DMCompositeLink *next;
138547c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite *)dmi->data;
138647c6ae99SBarry Smith   DM                      dm;
138747c6ae99SBarry Smith 
138847c6ae99SBarry Smith   PetscFunctionBegin;
138947c6ae99SBarry Smith   PetscValidHeaderSpecific(dmi, DM_CLASSID, 1);
139048a46eb9SPierre Jolivet   if (comm == MPI_COMM_NULL) PetscCall(PetscObjectGetComm((PetscObject)dmi, &comm));
13919566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dmi));
139247c6ae99SBarry Smith   next = com->next;
13939566063dSJacob Faibussowitsch   PetscCall(DMCompositeCreate(comm, fine));
139447c6ae99SBarry Smith 
139547c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
139647c6ae99SBarry Smith   while (next) {
13979566063dSJacob Faibussowitsch     PetscCall(DMRefine(next->dm, comm, &dm));
13989566063dSJacob Faibussowitsch     PetscCall(DMCompositeAddDM(*fine, dm));
13999566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)dm));
140047c6ae99SBarry Smith     next = next->next;
140147c6ae99SBarry Smith   }
140247c6ae99SBarry Smith   PetscFunctionReturn(0);
140347c6ae99SBarry Smith }
140447c6ae99SBarry Smith 
1405d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsen_Composite(DM dmi, MPI_Comm comm, DM *fine)
1406d71ae5a4SJacob Faibussowitsch {
140714354c39SJed Brown   struct DMCompositeLink *next;
140814354c39SJed Brown   DM_Composite           *com = (DM_Composite *)dmi->data;
140914354c39SJed Brown   DM                      dm;
141014354c39SJed Brown 
141114354c39SJed Brown   PetscFunctionBegin;
141214354c39SJed Brown   PetscValidHeaderSpecific(dmi, DM_CLASSID, 1);
14139566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dmi));
141448a46eb9SPierre Jolivet   if (comm == MPI_COMM_NULL) PetscCall(PetscObjectGetComm((PetscObject)dmi, &comm));
141514354c39SJed Brown   next = com->next;
14169566063dSJacob Faibussowitsch   PetscCall(DMCompositeCreate(comm, fine));
141714354c39SJed Brown 
141814354c39SJed Brown   /* loop over packed objects, handling one at at time */
141914354c39SJed Brown   while (next) {
14209566063dSJacob Faibussowitsch     PetscCall(DMCoarsen(next->dm, comm, &dm));
14219566063dSJacob Faibussowitsch     PetscCall(DMCompositeAddDM(*fine, dm));
14229566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)dm));
142314354c39SJed Brown     next = next->next;
142414354c39SJed Brown   }
142514354c39SJed Brown   PetscFunctionReturn(0);
142614354c39SJed Brown }
142747c6ae99SBarry Smith 
1428d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Composite(DM coarse, DM fine, Mat *A, Vec *v)
1429d71ae5a4SJacob Faibussowitsch {
14309ae5db72SJed Brown   PetscInt                m, n, M, N, nDM, i;
143147c6ae99SBarry Smith   struct DMCompositeLink *nextc;
143247c6ae99SBarry Smith   struct DMCompositeLink *nextf;
143325296bd5SBarry Smith   Vec                     gcoarse, gfine, *vecs;
143447c6ae99SBarry Smith   DM_Composite           *comcoarse = (DM_Composite *)coarse->data;
143547c6ae99SBarry Smith   DM_Composite           *comfine   = (DM_Composite *)fine->data;
14369ae5db72SJed Brown   Mat                    *mats;
143747c6ae99SBarry Smith 
143847c6ae99SBarry Smith   PetscFunctionBegin;
143947c6ae99SBarry Smith   PetscValidHeaderSpecific(coarse, DM_CLASSID, 1);
144047c6ae99SBarry Smith   PetscValidHeaderSpecific(fine, DM_CLASSID, 2);
14419566063dSJacob Faibussowitsch   PetscCall(DMSetUp(coarse));
14429566063dSJacob Faibussowitsch   PetscCall(DMSetUp(fine));
144347c6ae99SBarry Smith   /* use global vectors only for determining matrix layout */
14449566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalVector(coarse, &gcoarse));
14459566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalVector(fine, &gfine));
14469566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(gcoarse, &n));
14479566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(gfine, &m));
14489566063dSJacob Faibussowitsch   PetscCall(VecGetSize(gcoarse, &N));
14499566063dSJacob Faibussowitsch   PetscCall(VecGetSize(gfine, &M));
14509566063dSJacob Faibussowitsch   PetscCall(DMRestoreGlobalVector(coarse, &gcoarse));
14519566063dSJacob Faibussowitsch   PetscCall(DMRestoreGlobalVector(fine, &gfine));
145247c6ae99SBarry Smith 
14539ae5db72SJed Brown   nDM = comfine->nDM;
145463a3b9bcSJacob Faibussowitsch   PetscCheck(nDM == comcoarse->nDM, PetscObjectComm((PetscObject)fine), PETSC_ERR_ARG_INCOMP, "Fine DMComposite has %" PetscInt_FMT " entries, but coarse has %" PetscInt_FMT, nDM, comcoarse->nDM);
14559566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nDM * nDM, &mats));
145648a46eb9SPierre Jolivet   if (v) PetscCall(PetscCalloc1(nDM, &vecs));
145747c6ae99SBarry Smith 
145847c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
14599ae5db72SJed Brown   for (nextc = comcoarse->next, nextf = comfine->next, i = 0; nextc; nextc = nextc->next, nextf = nextf->next, i++) {
14601baa6e33SBarry Smith     if (!v) PetscCall(DMCreateInterpolation(nextc->dm, nextf->dm, &mats[i * nDM + i], NULL));
14611baa6e33SBarry Smith     else PetscCall(DMCreateInterpolation(nextc->dm, nextf->dm, &mats[i * nDM + i], &vecs[i]));
146247c6ae99SBarry Smith   }
14639566063dSJacob Faibussowitsch   PetscCall(MatCreateNest(PetscObjectComm((PetscObject)fine), nDM, NULL, nDM, NULL, mats, A));
14641baa6e33SBarry Smith   if (v) PetscCall(VecCreateNest(PetscObjectComm((PetscObject)fine), nDM, NULL, vecs, v));
14659566063dSJacob Faibussowitsch   for (i = 0; i < nDM * nDM; i++) PetscCall(MatDestroy(&mats[i]));
14669566063dSJacob Faibussowitsch   PetscCall(PetscFree(mats));
146725296bd5SBarry Smith   if (v) {
14689566063dSJacob Faibussowitsch     for (i = 0; i < nDM; i++) PetscCall(VecDestroy(&vecs[i]));
14699566063dSJacob Faibussowitsch     PetscCall(PetscFree(vecs));
147025296bd5SBarry Smith   }
147147c6ae99SBarry Smith   PetscFunctionReturn(0);
147247c6ae99SBarry Smith }
147347c6ae99SBarry Smith 
1474d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetLocalToGlobalMapping_Composite(DM dm)
1475d71ae5a4SJacob Faibussowitsch {
14761411c6eeSJed Brown   DM_Composite           *com = (DM_Composite *)dm->data;
14771411c6eeSJed Brown   ISLocalToGlobalMapping *ltogs;
1478f7efa3c7SJed Brown   PetscInt                i;
14791411c6eeSJed Brown 
14801411c6eeSJed Brown   PetscFunctionBegin;
14811411c6eeSJed Brown   /* Set the ISLocalToGlobalMapping on the new matrix */
14829566063dSJacob Faibussowitsch   PetscCall(DMCompositeGetISLocalToGlobalMappings(dm, &ltogs));
14839566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingConcatenate(PetscObjectComm((PetscObject)dm), com->nDM, ltogs, &dm->ltogmap));
14849566063dSJacob Faibussowitsch   for (i = 0; i < com->nDM; i++) PetscCall(ISLocalToGlobalMappingDestroy(&ltogs[i]));
14859566063dSJacob Faibussowitsch   PetscCall(PetscFree(ltogs));
14861411c6eeSJed Brown   PetscFunctionReturn(0);
14871411c6eeSJed Brown }
14881411c6eeSJed Brown 
1489d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateColoring_Composite(DM dm, ISColoringType ctype, ISColoring *coloring)
1490d71ae5a4SJacob Faibussowitsch {
149147c6ae99SBarry Smith   PetscInt         n, i, cnt;
149247c6ae99SBarry Smith   ISColoringValue *colors;
149347c6ae99SBarry Smith   PetscBool        dense  = PETSC_FALSE;
149447c6ae99SBarry Smith   ISColoringValue  maxcol = 0;
149547c6ae99SBarry Smith   DM_Composite    *com    = (DM_Composite *)dm->data;
149647c6ae99SBarry Smith 
149747c6ae99SBarry Smith   PetscFunctionBegin;
149847c6ae99SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
149908401ef6SPierre Jolivet   PetscCheck(ctype != IS_COLORING_LOCAL, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only global coloring supported");
1500f7d195e4SLawrence Mitchell   if (ctype == IS_COLORING_GLOBAL) {
150147c6ae99SBarry Smith     n = com->n;
1502ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Unknown ISColoringType");
15039566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n, &colors)); /* freed in ISColoringDestroy() */
150447c6ae99SBarry Smith 
15059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dmcomposite_dense_jacobian", &dense, NULL));
150647c6ae99SBarry Smith   if (dense) {
1507ad540459SPierre Jolivet     for (i = 0; i < n; i++) colors[i] = (ISColoringValue)(com->rstart + i);
150847c6ae99SBarry Smith     maxcol = com->N;
150947c6ae99SBarry Smith   } else {
151047c6ae99SBarry Smith     struct DMCompositeLink *next = com->next;
151147c6ae99SBarry Smith     PetscMPIInt             rank;
151247c6ae99SBarry Smith 
15139566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
151447c6ae99SBarry Smith     cnt = 0;
151547c6ae99SBarry Smith     while (next) {
151647c6ae99SBarry Smith       ISColoring lcoloring;
151747c6ae99SBarry Smith 
15189566063dSJacob Faibussowitsch       PetscCall(DMCreateColoring(next->dm, IS_COLORING_GLOBAL, &lcoloring));
1519ad540459SPierre Jolivet       for (i = 0; i < lcoloring->N; i++) colors[cnt++] = maxcol + lcoloring->colors[i];
152047c6ae99SBarry Smith       maxcol += lcoloring->n;
15219566063dSJacob Faibussowitsch       PetscCall(ISColoringDestroy(&lcoloring));
152247c6ae99SBarry Smith       next = next->next;
152347c6ae99SBarry Smith     }
152447c6ae99SBarry Smith   }
15259566063dSJacob Faibussowitsch   PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)dm), maxcol, n, colors, PETSC_OWN_POINTER, coloring));
152647c6ae99SBarry Smith   PetscFunctionReturn(0);
152747c6ae99SBarry Smith }
152847c6ae99SBarry Smith 
1529d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocalBegin_Composite(DM dm, Vec gvec, InsertMode mode, Vec lvec)
1530d71ae5a4SJacob Faibussowitsch {
153147c6ae99SBarry Smith   struct DMCompositeLink *next;
153247c6ae99SBarry Smith   PetscScalar            *garray, *larray;
153347c6ae99SBarry Smith   DM_Composite           *com = (DM_Composite *)dm->data;
153447c6ae99SBarry Smith 
153547c6ae99SBarry Smith   PetscFunctionBegin;
153647c6ae99SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
153747c6ae99SBarry Smith   PetscValidHeaderSpecific(gvec, VEC_CLASSID, 2);
153839d35262SVincent Le Chenadec 
153948a46eb9SPierre Jolivet   if (!com->setup) PetscCall(DMSetUp(dm));
154039d35262SVincent Le Chenadec 
15419566063dSJacob Faibussowitsch   PetscCall(VecGetArray(gvec, &garray));
15429566063dSJacob Faibussowitsch   PetscCall(VecGetArray(lvec, &larray));
154347c6ae99SBarry Smith 
154447c6ae99SBarry Smith   /* loop over packed objects, handling one at at time */
154539d35262SVincent Le Chenadec   next = com->next;
154647c6ae99SBarry Smith   while (next) {
154747c6ae99SBarry Smith     Vec      local, global;
154847c6ae99SBarry Smith     PetscInt N;
154947c6ae99SBarry Smith 
15509566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(next->dm, &global));
15519566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(global, &N));
15529566063dSJacob Faibussowitsch     PetscCall(VecPlaceArray(global, garray));
15539566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(next->dm, &local));
15549566063dSJacob Faibussowitsch     PetscCall(VecPlaceArray(local, larray));
15559566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(next->dm, global, mode, local));
15569566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(next->dm, global, mode, local));
15579566063dSJacob Faibussowitsch     PetscCall(VecResetArray(global));
15589566063dSJacob Faibussowitsch     PetscCall(VecResetArray(local));
15599566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(next->dm, &global));
15609566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(next->dm, &local));
156139d35262SVincent Le Chenadec 
156206ebdd98SJed Brown     larray += next->nlocal;
156339d35262SVincent Le Chenadec     garray += next->n;
156447c6ae99SBarry Smith     next = next->next;
156547c6ae99SBarry Smith   }
156647c6ae99SBarry Smith 
15679566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(gvec, NULL));
15689566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(lvec, NULL));
156947c6ae99SBarry Smith   PetscFunctionReturn(0);
157047c6ae99SBarry Smith }
157147c6ae99SBarry Smith 
1572d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocalEnd_Composite(DM dm, Vec gvec, InsertMode mode, Vec lvec)
1573d71ae5a4SJacob Faibussowitsch {
15740c010503SBarry Smith   PetscFunctionBegin;
157539d35262SVincent Le Chenadec   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
157639d35262SVincent Le Chenadec   PetscValidHeaderSpecific(gvec, VEC_CLASSID, 2);
157739d35262SVincent Le Chenadec   PetscValidHeaderSpecific(lvec, VEC_CLASSID, 4);
157839d35262SVincent Le Chenadec   PetscFunctionReturn(0);
157939d35262SVincent Le Chenadec }
158039d35262SVincent Le Chenadec 
1581d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobalBegin_Composite(DM dm, Vec lvec, InsertMode mode, Vec gvec)
1582d71ae5a4SJacob Faibussowitsch {
158339d35262SVincent Le Chenadec   struct DMCompositeLink *next;
158439d35262SVincent Le Chenadec   PetscScalar            *larray, *garray;
158539d35262SVincent Le Chenadec   DM_Composite           *com = (DM_Composite *)dm->data;
158639d35262SVincent Le Chenadec 
158739d35262SVincent Le Chenadec   PetscFunctionBegin;
158839d35262SVincent Le Chenadec   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
158939d35262SVincent Le Chenadec   PetscValidHeaderSpecific(lvec, VEC_CLASSID, 2);
159039d35262SVincent Le Chenadec   PetscValidHeaderSpecific(gvec, VEC_CLASSID, 4);
159139d35262SVincent Le Chenadec 
159248a46eb9SPierre Jolivet   if (!com->setup) PetscCall(DMSetUp(dm));
159339d35262SVincent Le Chenadec 
15949566063dSJacob Faibussowitsch   PetscCall(VecGetArray(lvec, &larray));
15959566063dSJacob Faibussowitsch   PetscCall(VecGetArray(gvec, &garray));
159639d35262SVincent Le Chenadec 
159739d35262SVincent Le Chenadec   /* loop over packed objects, handling one at at time */
159839d35262SVincent Le Chenadec   next = com->next;
159939d35262SVincent Le Chenadec   while (next) {
160039d35262SVincent Le Chenadec     Vec global, local;
160139d35262SVincent Le Chenadec 
16029566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(next->dm, &local));
16039566063dSJacob Faibussowitsch     PetscCall(VecPlaceArray(local, larray));
16049566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(next->dm, &global));
16059566063dSJacob Faibussowitsch     PetscCall(VecPlaceArray(global, garray));
16069566063dSJacob Faibussowitsch     PetscCall(DMLocalToGlobalBegin(next->dm, local, mode, global));
16079566063dSJacob Faibussowitsch     PetscCall(DMLocalToGlobalEnd(next->dm, local, mode, global));
16089566063dSJacob Faibussowitsch     PetscCall(VecResetArray(local));
16099566063dSJacob Faibussowitsch     PetscCall(VecResetArray(global));
16109566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(next->dm, &global));
16119566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(next->dm, &local));
161239d35262SVincent Le Chenadec 
161339d35262SVincent Le Chenadec     garray += next->n;
161439d35262SVincent Le Chenadec     larray += next->nlocal;
161539d35262SVincent Le Chenadec     next = next->next;
161639d35262SVincent Le Chenadec   }
161739d35262SVincent Le Chenadec 
16189566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(gvec, NULL));
16199566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(lvec, NULL));
162039d35262SVincent Le Chenadec 
162139d35262SVincent Le Chenadec   PetscFunctionReturn(0);
162239d35262SVincent Le Chenadec }
162339d35262SVincent Le Chenadec 
1624d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobalEnd_Composite(DM dm, Vec lvec, InsertMode mode, Vec gvec)
1625d71ae5a4SJacob Faibussowitsch {
162639d35262SVincent Le Chenadec   PetscFunctionBegin;
162739d35262SVincent Le Chenadec   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
162839d35262SVincent Le Chenadec   PetscValidHeaderSpecific(lvec, VEC_CLASSID, 2);
162939d35262SVincent Le Chenadec   PetscValidHeaderSpecific(gvec, VEC_CLASSID, 4);
163039d35262SVincent Le Chenadec   PetscFunctionReturn(0);
163139d35262SVincent Le Chenadec }
163239d35262SVincent Le Chenadec 
1633d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToLocalBegin_Composite(DM dm, Vec vec1, InsertMode mode, Vec vec2)
1634d71ae5a4SJacob Faibussowitsch {
163539d35262SVincent Le Chenadec   struct DMCompositeLink *next;
163639d35262SVincent Le Chenadec   PetscScalar            *array1, *array2;
163739d35262SVincent Le Chenadec   DM_Composite           *com = (DM_Composite *)dm->data;
163839d35262SVincent Le Chenadec 
163939d35262SVincent Le Chenadec   PetscFunctionBegin;
164039d35262SVincent Le Chenadec   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
164139d35262SVincent Le Chenadec   PetscValidHeaderSpecific(vec1, VEC_CLASSID, 2);
164239d35262SVincent Le Chenadec   PetscValidHeaderSpecific(vec2, VEC_CLASSID, 4);
164339d35262SVincent Le Chenadec 
164448a46eb9SPierre Jolivet   if (!com->setup) PetscCall(DMSetUp(dm));
164539d35262SVincent Le Chenadec 
16469566063dSJacob Faibussowitsch   PetscCall(VecGetArray(vec1, &array1));
16479566063dSJacob Faibussowitsch   PetscCall(VecGetArray(vec2, &array2));
164839d35262SVincent Le Chenadec 
164939d35262SVincent Le Chenadec   /* loop over packed objects, handling one at at time */
165039d35262SVincent Le Chenadec   next = com->next;
165139d35262SVincent Le Chenadec   while (next) {
165239d35262SVincent Le Chenadec     Vec local1, local2;
165339d35262SVincent Le Chenadec 
16549566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(next->dm, &local1));
16559566063dSJacob Faibussowitsch     PetscCall(VecPlaceArray(local1, array1));
16569566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(next->dm, &local2));
16579566063dSJacob Faibussowitsch     PetscCall(VecPlaceArray(local2, array2));
16589566063dSJacob Faibussowitsch     PetscCall(DMLocalToLocalBegin(next->dm, local1, mode, local2));
16599566063dSJacob Faibussowitsch     PetscCall(DMLocalToLocalEnd(next->dm, local1, mode, local2));
16609566063dSJacob Faibussowitsch     PetscCall(VecResetArray(local2));
16619566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(next->dm, &local2));
16629566063dSJacob Faibussowitsch     PetscCall(VecResetArray(local1));
16639566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(next->dm, &local1));
166439d35262SVincent Le Chenadec 
166539d35262SVincent Le Chenadec     array1 += next->nlocal;
166639d35262SVincent Le Chenadec     array2 += next->nlocal;
166739d35262SVincent Le Chenadec     next = next->next;
166839d35262SVincent Le Chenadec   }
166939d35262SVincent Le Chenadec 
16709566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(vec1, NULL));
16719566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(vec2, NULL));
167239d35262SVincent Le Chenadec 
167339d35262SVincent Le Chenadec   PetscFunctionReturn(0);
167439d35262SVincent Le Chenadec }
167539d35262SVincent Le Chenadec 
1676d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToLocalEnd_Composite(DM dm, Vec lvec, InsertMode mode, Vec gvec)
1677d71ae5a4SJacob Faibussowitsch {
167839d35262SVincent Le Chenadec   PetscFunctionBegin;
167939d35262SVincent Le Chenadec   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
168039d35262SVincent Le Chenadec   PetscValidHeaderSpecific(lvec, VEC_CLASSID, 2);
168139d35262SVincent Le Chenadec   PetscValidHeaderSpecific(gvec, VEC_CLASSID, 4);
16820c010503SBarry Smith   PetscFunctionReturn(0);
16830c010503SBarry Smith }
168447c6ae99SBarry Smith 
16856ae3a549SBarry Smith /*MC
1686*dce8aebaSBarry Smith    DMCOMPOSITE = "composite" - A `DM` object that is used to manage data for a collection of `DM`
16876ae3a549SBarry Smith 
16886ae3a549SBarry Smith   Level: intermediate
16896ae3a549SBarry Smith 
1690db781477SPatrick Sanan .seealso: `DMType`, `DM`, `DMDACreate()`, `DMCreate()`, `DMSetType()`, `DMCompositeCreate()`
16916ae3a549SBarry Smith M*/
16926ae3a549SBarry Smith 
1693d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Composite(DM p)
1694d71ae5a4SJacob Faibussowitsch {
1695a4121054SBarry Smith   DM_Composite *com;
1696a4121054SBarry Smith 
1697a4121054SBarry Smith   PetscFunctionBegin;
16984dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&com));
1699a4121054SBarry Smith   p->data     = com;
1700a4121054SBarry Smith   com->n      = 0;
17017ac2b803SAlex Fikl   com->nghost = 0;
17020298fd71SBarry Smith   com->next   = NULL;
1703a4121054SBarry Smith   com->nDM    = 0;
1704a4121054SBarry Smith 
1705a4121054SBarry Smith   p->ops->createglobalvector       = DMCreateGlobalVector_Composite;
1706a4121054SBarry Smith   p->ops->createlocalvector        = DMCreateLocalVector_Composite;
1707184d77edSJed Brown   p->ops->getlocaltoglobalmapping  = DMGetLocalToGlobalMapping_Composite;
17084d343eeaSMatthew G Knepley   p->ops->createfieldis            = DMCreateFieldIS_Composite;
170916621825SDmitry Karpeev   p->ops->createfielddecomposition = DMCreateFieldDecomposition_Composite;
1710a4121054SBarry Smith   p->ops->refine                   = DMRefine_Composite;
171114354c39SJed Brown   p->ops->coarsen                  = DMCoarsen_Composite;
171225296bd5SBarry Smith   p->ops->createinterpolation      = DMCreateInterpolation_Composite;
171325296bd5SBarry Smith   p->ops->creatematrix             = DMCreateMatrix_Composite;
1714e727c939SJed Brown   p->ops->getcoloring              = DMCreateColoring_Composite;
1715a4121054SBarry Smith   p->ops->globaltolocalbegin       = DMGlobalToLocalBegin_Composite;
1716a4121054SBarry Smith   p->ops->globaltolocalend         = DMGlobalToLocalEnd_Composite;
171739d35262SVincent Le Chenadec   p->ops->localtoglobalbegin       = DMLocalToGlobalBegin_Composite;
171839d35262SVincent Le Chenadec   p->ops->localtoglobalend         = DMLocalToGlobalEnd_Composite;
171939d35262SVincent Le Chenadec   p->ops->localtolocalbegin        = DMLocalToLocalBegin_Composite;
172039d35262SVincent Le Chenadec   p->ops->localtolocalend          = DMLocalToLocalEnd_Composite;
1721a4121054SBarry Smith   p->ops->destroy                  = DMDestroy_Composite;
1722a4121054SBarry Smith   p->ops->view                     = DMView_Composite;
1723a4121054SBarry Smith   p->ops->setup                    = DMSetUp_Composite;
1724e10fd815SStefano Zampini 
17259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)p, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Composite));
1726a4121054SBarry Smith   PetscFunctionReturn(0);
1727a4121054SBarry Smith }
1728a4121054SBarry Smith 
17291fd49c25SBarry Smith /*@
1730*dce8aebaSBarry Smith     DMCompositeCreate - Creates a `DMCOMPOSITE`, used to generate "composite"
17310c010503SBarry Smith       vectors made up of several subvectors.
17320c010503SBarry Smith 
1733d083f849SBarry Smith     Collective
173447c6ae99SBarry Smith 
173547c6ae99SBarry Smith     Input Parameter:
17360c010503SBarry Smith .   comm - the processors that will share the global vector
17370c010503SBarry Smith 
17380c010503SBarry Smith     Output Parameters:
1739*dce8aebaSBarry Smith .   packer - the `DMCOMPOSITE` object
174047c6ae99SBarry Smith 
174147c6ae99SBarry Smith     Level: advanced
174247c6ae99SBarry Smith 
1743*dce8aebaSBarry Smith .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCompositeScatter()`, `DMCOMPOSITE`, `DMCreate()`
1744db781477SPatrick Sanan           `DMCompositeGather()`, `DMCreateGlobalVector()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`
1745db781477SPatrick Sanan           `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()`
174647c6ae99SBarry Smith @*/
1747d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompositeCreate(MPI_Comm comm, DM *packer)
1748d71ae5a4SJacob Faibussowitsch {
174947c6ae99SBarry Smith   PetscFunctionBegin;
17500c010503SBarry Smith   PetscValidPointer(packer, 2);
17519566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, packer));
17529566063dSJacob Faibussowitsch   PetscCall(DMSetType(*packer, DMCOMPOSITE));
175347c6ae99SBarry Smith   PetscFunctionReturn(0);
175447c6ae99SBarry Smith }
1755