xref: /petsc/src/dm/impls/composite/pack.c (revision 3ba1676111f5c958fe6c2729b46ca4d523958bb3)
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
9dce8aebaSBarry 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 
19dce8aebaSBarry Smith     Note:
20dce8aebaSBarry Smith     See `DMSetApplicationContext()` and `DMGetApplicationContext()` for how to get user information into
2147c6ae99SBarry Smith     this routine
2247c6ae99SBarry Smith 
23dce8aebaSBarry Smith     Fortran Note:
24dce8aebaSBarry Smith     Not available from Fortran
25dce8aebaSBarry Smith 
26dce8aebaSBarry 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;
37*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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));
57*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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   }
82*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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;
117*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11847c6ae99SBarry Smith }
11947c6ae99SBarry Smith 
12047c6ae99SBarry Smith /* ----------------------------------------------------------------------------------*/
12147c6ae99SBarry Smith 
12273e31fe2SJed Brown /*@
123dce8aebaSBarry 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:
129dce8aebaSBarry Smith .    dm - the `DMCOMPOSITE` object
13047c6ae99SBarry Smith 
13147c6ae99SBarry Smith     Output Parameter:
132dce8aebaSBarry Smith .     nDM - the number of `DM`
13347c6ae99SBarry Smith 
13447c6ae99SBarry Smith     Level: beginner
13547c6ae99SBarry Smith 
136dce8aebaSBarry 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;
148*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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:
158dce8aebaSBarry 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 
166dce8aebaSBarry Smith     Note:
167dce8aebaSBarry Smith     Use `DMCompositeRestoreAccess()` to return the vectors when you no longer need them
168dce8aebaSBarry Smith 
169dce8aebaSBarry Smith     Fortran Note:
170dce8aebaSBarry Smith     Fortran callers must use numbered versions of this routine, e.g., DMCompositeGetAccess4(dm,gvec,vec1,vec2,vec3,vec4)
171dce8aebaSBarry Smith     or use the alternative interface `DMCompositeGetAccessArray()`.
172dce8aebaSBarry Smith 
173dce8aebaSBarry 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);
215*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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:
225dce8aebaSBarry 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 
235dce8aebaSBarry Smith     Note:
236dce8aebaSBarry Smith     Use `DMCompositeRestoreAccessArray()` to return the vectors when you no longer need them
237dce8aebaSBarry Smith 
238dce8aebaSBarry 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   }
275*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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:
285dce8aebaSBarry 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 
295dce8aebaSBarry Smith     Note:
296dce8aebaSBarry Smith     Use `DMCompositeRestoreLocalAccessArray()` to return the vectors
297dce8aebaSBarry Smith     when you no longer need them.
298dce8aebaSBarry Smith 
299dce8aebaSBarry 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 
342*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3437ac2b803SAlex Fikl }
3447ac2b803SAlex Fikl 
34547c6ae99SBarry Smith /*@C
346dce8aebaSBarry Smith     DMCompositeRestoreAccess - Returns the vectors obtained with `DMCompositeGetAccess()`
34747c6ae99SBarry Smith        representation.
34847c6ae99SBarry Smith 
349d083f849SBarry Smith     Collective on dm
35047c6ae99SBarry Smith 
3519ae5db72SJed Brown     Input Parameters:
352dce8aebaSBarry 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 
358dce8aebaSBarry 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);
392*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39347c6ae99SBarry Smith }
39447c6ae99SBarry Smith 
395f73e5cebSJed Brown /*@C
396dce8aebaSBarry Smith     DMCompositeRestoreAccessArray - Returns the vectors obtained with `DMCompositeGetAccessArray()`
397f73e5cebSJed Brown 
398d083f849SBarry Smith     Collective on dm
399f73e5cebSJed Brown 
400f73e5cebSJed Brown     Input Parameters:
401dce8aebaSBarry 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 
409dce8aebaSBarry 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   }
435*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
436f73e5cebSJed Brown }
437f73e5cebSJed Brown 
4387ac2b803SAlex Fikl /*@C
439dce8aebaSBarry Smith     DMCompositeRestoreLocalAccessArray - Returns the vectors obtained with `DMCompositeGetLocalAccessArray()`.
4407ac2b803SAlex Fikl 
441d083f849SBarry Smith     Collective on dm.
4427ac2b803SAlex Fikl 
4437ac2b803SAlex Fikl     Input Parameters:
444dce8aebaSBarry 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 
452dce8aebaSBarry Smith     Note:
453dce8aebaSBarry Smith     nwanted and wanted must match the values given to `DMCompositeGetLocalAccessArray()`
4547ac2b803SAlex Fikl     otherwise the call will fail.
4557ac2b803SAlex Fikl 
456dce8aebaSBarry 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   }
484*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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:
493dce8aebaSBarry 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 
499dce8aebaSBarry Smith     Note:
500dce8aebaSBarry Smith     `DMCompositeScatterArray()` is a non-variadic alternative that is often more convenient for library callers and is
5016f3c3dcfSJed Brown     accessible from Fortran.
5026f3c3dcfSJed Brown 
503dce8aebaSBarry 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);
543*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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:
552dce8aebaSBarry 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:
559dce8aebaSBarry Smith     This is a non-variadic alternative to `DMCompositeScatter()`
5606f3c3dcfSJed Brown 
561dce8aebaSBarry 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   }
595*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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:
604dce8aebaSBarry Smith +    dm - the `DMCOMPOSITE` object
60547c6ae99SBarry Smith .    gvec - the global vector
606dce8aebaSBarry 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 
611dce8aebaSBarry Smith     Fortran Note:
612dce8aebaSBarry Smith     Fortran users should use `DMCompositeGatherArray()`
613f5f57ec0SBarry Smith 
614dce8aebaSBarry 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);
653*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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:
662dce8aebaSBarry Smith +    dm - the `DMCOMPOSITE` object
6636f3c3dcfSJed Brown .    gvec - the global vector
664dce8aebaSBarry 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 
669dce8aebaSBarry Smith     Note:
670dce8aebaSBarry Smith     This is a non-variadic alternative to `DMCompositeGather()`.
6716f3c3dcfSJed Brown 
672dce8aebaSBarry 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   }
706*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7076f3c3dcfSJed Brown }
7086f3c3dcfSJed Brown 
709f5f57ec0SBarry Smith /*@
710dce8aebaSBarry Smith     DMCompositeAddDM - adds a `DM` vector to a `DMCOMPOSITE`
71147c6ae99SBarry Smith 
712d083f849SBarry Smith     Collective on dm
71347c6ae99SBarry Smith 
714d8d19677SJose E. Roman     Input Parameters:
715dce8aebaSBarry Smith +    dmc - the  `DMCOMPOSITE` object
716dce8aebaSBarry Smith -    dm - the `DM` object
71747c6ae99SBarry Smith 
71847c6ae99SBarry Smith     Level: advanced
71947c6ae99SBarry Smith 
720dce8aebaSBarry 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++;
765*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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   }
811*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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));
827*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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));
844*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
84547c6ae99SBarry Smith }
84647c6ae99SBarry Smith 
84747c6ae99SBarry Smith /*@C
848dce8aebaSBarry Smith     DMCompositeGetISLocalToGlobalMappings - gets an `ISLocalToGlobalMapping` for each `DM` in the `DMCOMPOSITE`, maps to the composite global space
84947c6ae99SBarry Smith 
850dce8aebaSBarry Smith     Collective on dm
85147c6ae99SBarry Smith 
85247c6ae99SBarry Smith     Input Parameter:
853dce8aebaSBarry 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
857dce8aebaSBarry Smith            all the ghost points that individual ghosted `DMDA` may have.
85847c6ae99SBarry Smith 
85947c6ae99SBarry Smith     Level: advanced
86047c6ae99SBarry Smith 
861dce8aebaSBarry Smith     Note:
862dce8aebaSBarry Smith     Each entry of ltogs should be destroyed with `ISLocalToGlobalMappingDestroy()`, the ltogs array should be freed with `PetscFree()`.
86347c6ae99SBarry Smith 
864dce8aebaSBarry Smith     Fortran Note:
865f5f57ec0SBarry Smith     Not available from Fortran
866f5f57ec0SBarry Smith 
867dce8aebaSBarry 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   }
930*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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:
939dce8aebaSBarry Smith . dm - the `DMCOMPOSITE`
94087c85e80SJed Brown 
9414165533cSJose E. Roman    Output Parameter:
942dce8aebaSBarry 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
948dce8aebaSBarry 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 
951dce8aebaSBarry Smith    To get the composite global indices at all local points (including ghosts), use `DMCompositeGetISLocalToGlobalMappings()`.
95287c85e80SJed Brown 
953dce8aebaSBarry Smith    To get index sets for pieces of the composite global vector, use `DMCompositeGetGlobalISs()`.
95487c85e80SJed Brown 
955dce8aebaSBarry Smith    Each returned `IS` should be destroyed with `ISDestroy()`, the array should be freed with `PetscFree()`.
95687c85e80SJed Brown 
957dce8aebaSBarry Smith    Fortran Note:
958f5f57ec0SBarry Smith    Not available from Fortran
959f5f57ec0SBarry Smith 
960dce8aebaSBarry 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   }
981*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
98287c85e80SJed Brown }
98387c85e80SJed Brown 
98447c6ae99SBarry Smith /*@C
985dce8aebaSBarry 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:
990dce8aebaSBarry 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:
998dce8aebaSBarry 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 
1002dce8aebaSBarry Smith        Use `DMCompositeGetLocalISs()` for index sets in the packed local numbering, and
1003dce8aebaSBarry Smith        `DMCompositeGetISLocalToGlobalMappings()` for to map local sub-`DM` (including ghost) indices to packed global
10046eb61c8cSJed Brown        indices.
100547c6ae99SBarry Smith 
1006dce8aebaSBarry Smith     Fortran Note:
1007dce8aebaSBarry Smith     The output argument 'is' must be an allocated array of sufficient length, which can be learned using `DMCompositeGetNumberDM()`.
1008f3cb0f7eSJed Brown 
1009dce8aebaSBarry 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   }
1056*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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   }
1098*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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   }
1119*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1120e7c4fc90SDmitry Karpeev }
1121e7c4fc90SDmitry Karpeev 
112247c6ae99SBarry Smith /* -------------------------------------------------------------------------------------*/
112347c6ae99SBarry Smith /*@C
1124dce8aebaSBarry Smith     DMCompositeGetLocalVectors - Gets local vectors for each part of a `DMCOMPOSITE`
1125dce8aebaSBarry Smith        Use `DMCompositeRestoreLocalVectors()` to return them.
112647c6ae99SBarry Smith 
112747c6ae99SBarry Smith     Not Collective
112847c6ae99SBarry Smith 
112947c6ae99SBarry Smith     Input Parameter:
1130dce8aebaSBarry 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 
1137dce8aebaSBarry Smith     Fortran Note:
1138f5f57ec0SBarry Smith     Not available from Fortran
1139f5f57ec0SBarry Smith 
1140dce8aebaSBarry 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);
1165*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
116647c6ae99SBarry Smith }
116747c6ae99SBarry Smith 
116847c6ae99SBarry Smith /*@C
1169dce8aebaSBarry Smith     DMCompositeRestoreLocalVectors - Restores local vectors for each part of a `DMCOMPOSITE`
117047c6ae99SBarry Smith 
117147c6ae99SBarry Smith     Not Collective
117247c6ae99SBarry Smith 
117347c6ae99SBarry Smith     Input Parameter:
1174dce8aebaSBarry Smith .    dm - the `DMCOMPOSITE` object
117547c6ae99SBarry Smith 
117647c6ae99SBarry Smith     Output Parameter:
1177dce8aebaSBarry Smith .   Vec ... - the individual sequential `Vec`
117847c6ae99SBarry Smith 
117947c6ae99SBarry Smith     Level: advanced
118047c6ae99SBarry Smith 
1181dce8aebaSBarry Smith     Fortran Note:
1182f5f57ec0SBarry Smith     Not available from Fortran
1183f5f57ec0SBarry Smith 
1184dce8aebaSBarry 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);
1209*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
121047c6ae99SBarry Smith }
121147c6ae99SBarry Smith 
121247c6ae99SBarry Smith /* -------------------------------------------------------------------------------------*/
121347c6ae99SBarry Smith /*@C
1214dce8aebaSBarry Smith     DMCompositeGetEntries - Gets the `DM` for each entry in a `DMCOMPOSITE`.
121547c6ae99SBarry Smith 
121647c6ae99SBarry Smith     Not Collective
121747c6ae99SBarry Smith 
121847c6ae99SBarry Smith     Input Parameter:
1219dce8aebaSBarry Smith .    dm - the `DMCOMPOSITE` object
122047c6ae99SBarry Smith 
122147c6ae99SBarry Smith     Output Parameter:
1222dce8aebaSBarry Smith .   DM ... - the individual entries `DM`
122347c6ae99SBarry Smith 
122447c6ae99SBarry Smith     Level: advanced
122547c6ae99SBarry Smith 
1226dce8aebaSBarry Smith     Fortran Note:
1227dce8aebaSBarry Smith     Available as `DMCompositeGetEntries()` for one output `DM`, DMCompositeGetEntries2() for 2, etc
1228f5f57ec0SBarry Smith 
1229dce8aebaSBarry 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);
1255*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
125647c6ae99SBarry Smith }
125747c6ae99SBarry Smith 
1258dbab29e1SMark F. Adams /*@C
1259dce8aebaSBarry Smith     DMCompositeGetEntriesArray - Gets the DM for each entry in a `DMCOMPOSITE`
12602fa5ba8aSJed Brown 
12612fa5ba8aSJed Brown     Not Collective
12622fa5ba8aSJed Brown 
12632fa5ba8aSJed Brown     Input Parameter:
1264dce8aebaSBarry Smith .    dm - the `DMCOMPOSITE` object
1265907376e6SBarry Smith 
1266907376e6SBarry Smith     Output Parameter:
1267dce8aebaSBarry Smith .    dms - array of sufficient length (see `DMCompositeGetNumberDM()`) to hold the individual `DM`
12682fa5ba8aSJed Brown 
12692fa5ba8aSJed Brown     Level: advanced
12702fa5ba8aSJed Brown 
1271dce8aebaSBarry 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;
1289*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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));
1309*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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));
1333*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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));
1379*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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   }
1402*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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   }
1425*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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   }
1471*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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));
1486*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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));
1526*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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));
1569*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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);
1578*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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 
1621*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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);
1630*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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 
1673*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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);
1682*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16830c010503SBarry Smith }
168447c6ae99SBarry Smith 
16856ae3a549SBarry Smith /*MC
1686dce8aebaSBarry 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));
1726*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1727a4121054SBarry Smith }
1728a4121054SBarry Smith 
17291fd49c25SBarry Smith /*@
1730dce8aebaSBarry 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:
1739dce8aebaSBarry Smith .   packer - the `DMCOMPOSITE` object
174047c6ae99SBarry Smith 
174147c6ae99SBarry Smith     Level: advanced
174247c6ae99SBarry Smith 
1743dce8aebaSBarry 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));
1753*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
175447c6ae99SBarry Smith }
1755