xref: /petsc/src/vec/is/utils/pmap.c (revision 9621ec185aeb287fa1ab4770f9eb19f72a96b4be)
169ce434fSBarry Smith 
269ce434fSBarry Smith /*
369ce434fSBarry Smith    This file contains routines for basic map object implementation.
469ce434fSBarry Smith */
569ce434fSBarry Smith 
6c3002683SMatthew G. Knepley #include <petscis.h> /*I "petscis.h" I*/
70c312b8eSJed Brown #include <petscsf.h>
807acc2aeSBarry Smith #include <petsc/private/isimpl.h>
95c25fcd7SBarry Smith 
10c3002683SMatthew G. Knepley /*@
11a8643c1eSVaclav Hapla   PetscLayoutCreate - Allocates PetscLayout space and sets the PetscLayout contents to the default.
1269ce434fSBarry Smith 
13d083f849SBarry Smith   Collective
1469ce434fSBarry Smith 
1569ce434fSBarry Smith   Input Parameters:
16a8643c1eSVaclav Hapla . comm - the MPI communicator
17a8643c1eSVaclav Hapla 
18a8643c1eSVaclav Hapla   Output Parameters:
19a8643c1eSVaclav Hapla . map - the new PetscLayout
2069ce434fSBarry Smith 
21456fcb79SJed Brown   Level: advanced
2269ce434fSBarry Smith 
23456fcb79SJed Brown   Notes:
24456fcb79SJed Brown   Typical calling sequence
25456fcb79SJed Brown .vb
2669ce434fSBarry Smith        PetscLayoutCreate(MPI_Comm,PetscLayout *);
27a8643c1eSVaclav Hapla        PetscLayoutSetBlockSize(PetscLayout,bs);
28a8643c1eSVaclav Hapla        PetscLayoutSetSize(PetscLayout,N); // or PetscLayoutSetLocalSize(PetscLayout,n);
2969ce434fSBarry Smith        PetscLayoutSetUp(PetscLayout);
30456fcb79SJed Brown .ve
31*9621ec18SVaclav Hapla   Alternatively,
32*9621ec18SVaclav Hapla $      PetscLayoutCreateFromSizes(comm,n,N,bs,&layout);
33*9621ec18SVaclav Hapla 
3469ce434fSBarry Smith   Optionally use any of the following:
35456fcb79SJed Brown 
36456fcb79SJed Brown + PetscLayoutGetSize(PetscLayout,PetscInt *);
37456fcb79SJed Brown . PetscLayoutGetLocalSize(PetscLayout,PetscInt *);
38456fcb79SJed Brown . PetscLayoutGetRange(PetscLayout,PetscInt *rstart,PetscInt *rend);
39456fcb79SJed Brown . PetscLayoutGetRanges(PetscLayout,const PetscInt *range[]);
40456fcb79SJed Brown - PetscLayoutDestroy(PetscLayout*);
4169ce434fSBarry Smith 
4269ce434fSBarry Smith   The PetscLayout object and methods are intended to be used in the PETSc Vec and Mat implementions; it is often not needed in
4369ce434fSBarry Smith   user codes unless you really gain something in their use.
4469ce434fSBarry Smith 
4569ce434fSBarry Smith .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
46*9621ec18SVaclav Hapla           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp(),
47*9621ec18SVaclav Hapla           PetscLayoutCreateFromSizes()
4869ce434fSBarry Smith 
4969ce434fSBarry Smith @*/
5069ce434fSBarry Smith PetscErrorCode PetscLayoutCreate(MPI_Comm comm,PetscLayout *map)
5169ce434fSBarry Smith {
5269ce434fSBarry Smith   PetscErrorCode ierr;
5369ce434fSBarry Smith 
5469ce434fSBarry Smith   PetscFunctionBegin;
55b00a9115SJed Brown   ierr = PetscNew(map);CHKERRQ(ierr);
5669ce434fSBarry Smith 
5769ce434fSBarry Smith   (*map)->comm        = comm;
5869ce434fSBarry Smith   (*map)->bs          = -1;
5969ce434fSBarry Smith   (*map)->n           = -1;
6069ce434fSBarry Smith   (*map)->N           = -1;
61f92d6284SStefano Zampini   (*map)->range       = NULL;
62*9621ec18SVaclav Hapla   (*map)->range_alloc = PETSC_TRUE;
6369ce434fSBarry Smith   (*map)->rstart      = 0;
6469ce434fSBarry Smith   (*map)->rend        = 0;
6569ce434fSBarry Smith   PetscFunctionReturn(0);
6669ce434fSBarry Smith }
6769ce434fSBarry Smith 
68c3002683SMatthew G. Knepley /*@
69*9621ec18SVaclav Hapla   PetscLayoutCreateFromSizes - Allocates PetscLayout space, sets the layout sizes, and sets the layout up.
70*9621ec18SVaclav Hapla 
71*9621ec18SVaclav Hapla   Collective
72*9621ec18SVaclav Hapla 
73*9621ec18SVaclav Hapla   Input Parameters:
74*9621ec18SVaclav Hapla + comm  - the MPI communicator
75*9621ec18SVaclav Hapla . n     - the local size (or PETSC_DECIDE)
76*9621ec18SVaclav Hapla . N     - the global size (or PETSC_DECIDE)
77*9621ec18SVaclav Hapla . bs    - the block size (or PETSC_DECIDE)
78*9621ec18SVaclav Hapla 
79*9621ec18SVaclav Hapla   Output Parameters:
80*9621ec18SVaclav Hapla . map - the new PetscLayout
81*9621ec18SVaclav Hapla 
82*9621ec18SVaclav Hapla   Level: advanced
83*9621ec18SVaclav Hapla 
84*9621ec18SVaclav Hapla   Notes:
85*9621ec18SVaclav Hapla $ PetscLayoutCreateFromSizes(comm,n,N,bs,&layout);
86*9621ec18SVaclav Hapla   is a shorthand for
87*9621ec18SVaclav Hapla .vb
88*9621ec18SVaclav Hapla   PetscLayoutCreate(comm,&layout);
89*9621ec18SVaclav Hapla   PetscLayoutSetLocalSize(layout,n);
90*9621ec18SVaclav Hapla   PetscLayoutSetSize(layout,N);
91*9621ec18SVaclav Hapla   PetscLayoutSetBlockSize(layout,bs);
92*9621ec18SVaclav Hapla   PetscLayoutSetUp(layout);
93*9621ec18SVaclav Hapla .ve
94*9621ec18SVaclav Hapla 
95*9621ec18SVaclav Hapla .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
96*9621ec18SVaclav Hapla           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp(), PetscLayoutCreateFromRanges()
97*9621ec18SVaclav Hapla 
98*9621ec18SVaclav Hapla @*/
99*9621ec18SVaclav Hapla PetscErrorCode PetscLayoutCreateFromSizes(MPI_Comm comm,PetscInt n,PetscInt N,PetscInt bs,PetscLayout *map)
100*9621ec18SVaclav Hapla {
101*9621ec18SVaclav Hapla   PetscErrorCode ierr;
102*9621ec18SVaclav Hapla 
103*9621ec18SVaclav Hapla   PetscFunctionBegin;
104*9621ec18SVaclav Hapla   ierr = PetscLayoutCreate(comm, map);CHKERRQ(ierr);
105*9621ec18SVaclav Hapla   ierr = PetscLayoutSetLocalSize(*map, n);CHKERRQ(ierr);
106*9621ec18SVaclav Hapla   ierr = PetscLayoutSetSize(*map, N);CHKERRQ(ierr);
107*9621ec18SVaclav Hapla   ierr = PetscLayoutSetBlockSize(*map, bs);CHKERRQ(ierr);
108*9621ec18SVaclav Hapla   ierr = PetscLayoutSetUp(*map);CHKERRQ(ierr);
109*9621ec18SVaclav Hapla   PetscFunctionReturn(0);
110*9621ec18SVaclav Hapla }
111*9621ec18SVaclav Hapla 
112*9621ec18SVaclav Hapla /*@
11369ce434fSBarry Smith   PetscLayoutDestroy - Frees a map object and frees its range if that exists.
11469ce434fSBarry Smith 
115d083f849SBarry Smith   Collective
11669ce434fSBarry Smith 
11769ce434fSBarry Smith   Input Parameters:
11869ce434fSBarry Smith . map - the PetscLayout
11969ce434fSBarry Smith 
12069ce434fSBarry Smith   Level: developer
12169ce434fSBarry Smith 
122c3002683SMatthew G. Knepley   Note:
12369ce434fSBarry Smith   The PetscLayout object and methods are intended to be used in the PETSc Vec and Mat implementions; it is
12469ce434fSBarry Smith   recommended they not be used in user codes unless you really gain something in their use.
12569ce434fSBarry Smith 
12669ce434fSBarry Smith .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutCreate(),
12769ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp()
12869ce434fSBarry Smith 
12969ce434fSBarry Smith @*/
13069ce434fSBarry Smith PetscErrorCode PetscLayoutDestroy(PetscLayout *map)
13169ce434fSBarry Smith {
13269ce434fSBarry Smith   PetscErrorCode ierr;
13369ce434fSBarry Smith 
13469ce434fSBarry Smith   PetscFunctionBegin;
13569ce434fSBarry Smith   if (!*map) PetscFunctionReturn(0);
13669ce434fSBarry Smith   if (!(*map)->refcnt--) {
137*9621ec18SVaclav Hapla     if ((*map)->range_alloc) {ierr = PetscFree((*map)->range);CHKERRQ(ierr);}
13869ce434fSBarry Smith     ierr = ISLocalToGlobalMappingDestroy(&(*map)->mapping);CHKERRQ(ierr);
13969ce434fSBarry Smith     ierr = PetscFree((*map));CHKERRQ(ierr);
14069ce434fSBarry Smith   }
14169ce434fSBarry Smith   *map = NULL;
14269ce434fSBarry Smith   PetscFunctionReturn(0);
14369ce434fSBarry Smith }
14469ce434fSBarry Smith 
145*9621ec18SVaclav Hapla /*@
146*9621ec18SVaclav Hapla   PetscLayoutCreateFromRanges - Creates a new PetscLayout with the given ownership ranges and sets it up.
147*9621ec18SVaclav Hapla 
148*9621ec18SVaclav Hapla   Collective
149*9621ec18SVaclav Hapla 
150*9621ec18SVaclav Hapla   Input Parameters:
151*9621ec18SVaclav Hapla + comm  - the MPI communicator
152*9621ec18SVaclav Hapla . range - the array of ownership ranges for each rank with length commsize+1
153*9621ec18SVaclav Hapla . mode  - the copy mode for range
154*9621ec18SVaclav Hapla - bs    - the block size (or PETSC_DECIDE)
155*9621ec18SVaclav Hapla 
156*9621ec18SVaclav Hapla   Output Parameters:
157*9621ec18SVaclav Hapla . newmap - the new PetscLayout
158*9621ec18SVaclav Hapla 
159*9621ec18SVaclav Hapla   Level: developer
160*9621ec18SVaclav Hapla 
161*9621ec18SVaclav Hapla .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
162*9621ec18SVaclav Hapla           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp(), PetscLayoutCreateFromSizes()
163*9621ec18SVaclav Hapla 
164*9621ec18SVaclav Hapla @*/
165*9621ec18SVaclav Hapla PetscErrorCode PetscLayoutCreateFromRanges(MPI_Comm comm,const PetscInt range[],PetscCopyMode mode,PetscInt bs,PetscLayout *newmap)
1667b659617SVaclav Hapla {
167*9621ec18SVaclav Hapla   PetscLayout    map;
1687b659617SVaclav Hapla   PetscMPIInt    rank,size;
1697b659617SVaclav Hapla   PetscErrorCode ierr;
1707b659617SVaclav Hapla 
1717b659617SVaclav Hapla   PetscFunctionBegin;
172*9621ec18SVaclav Hapla   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
173*9621ec18SVaclav Hapla   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
174*9621ec18SVaclav Hapla   ierr = PetscLayoutCreate(comm, &map);CHKERRQ(ierr);
175*9621ec18SVaclav Hapla   ierr = PetscLayoutSetBlockSize(map, bs);CHKERRQ(ierr);
176*9621ec18SVaclav Hapla   switch (mode) {
177*9621ec18SVaclav Hapla     case PETSC_COPY_VALUES:
178*9621ec18SVaclav Hapla       ierr = PetscMalloc1(size+1, &map->range);CHKERRQ(ierr);
179*9621ec18SVaclav Hapla       ierr = PetscArraycpy(map->range, range, size+1);CHKERRQ(ierr);
180*9621ec18SVaclav Hapla       break;
181*9621ec18SVaclav Hapla     case PETSC_USE_POINTER:
182*9621ec18SVaclav Hapla       map->range_alloc = PETSC_FALSE;
183*9621ec18SVaclav Hapla     default:
184*9621ec18SVaclav Hapla       map->range = (PetscInt*) range;
185*9621ec18SVaclav Hapla       break;
186*9621ec18SVaclav Hapla   }
1877b659617SVaclav Hapla   map->rstart = map->range[rank];
1887b659617SVaclav Hapla   map->rend   = map->range[rank+1];
1897b659617SVaclav Hapla   map->n      = map->rend - map->rstart;
1907b659617SVaclav Hapla   map->N      = map->range[size];
1917b659617SVaclav Hapla #if defined(PETSC_USE_DEBUG)
1927b659617SVaclav Hapla   /* just check that n, N and bs are consistent */
1937b659617SVaclav Hapla   {
1947b659617SVaclav Hapla     PetscInt tmp;
1957b659617SVaclav Hapla     ierr = MPIU_Allreduce(&map->n,&tmp,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
1967b659617SVaclav Hapla     if (tmp != map->N) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Sum of local lengths %D does not equal global length %D, my local length %D.\nThe provided PetscLayout is wrong.",tmp,map->N,map->n);
1977b659617SVaclav Hapla   }
1987b659617SVaclav Hapla   if (map->bs > 1) {
1997b659617SVaclav Hapla     if (map->n % map->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local size %D must be divisible by blocksize %D",map->n,map->bs);
2007b659617SVaclav Hapla   }
2017b659617SVaclav Hapla   if (map->bs > 1) {
2027b659617SVaclav Hapla     if (map->N % map->bs) SETERRQ2(map->comm,PETSC_ERR_PLIB,"Global size %D must be divisible by blocksize %D",map->N,map->bs);
2037b659617SVaclav Hapla   }
2047b659617SVaclav Hapla #endif
205*9621ec18SVaclav Hapla   *newmap = map;
2067b659617SVaclav Hapla   PetscFunctionReturn(0);
2077b659617SVaclav Hapla }
2087b659617SVaclav Hapla 
209c3002683SMatthew G. Knepley /*@
21069ce434fSBarry Smith   PetscLayoutSetUp - given a map where you have set either the global or local
21169ce434fSBarry Smith                      size sets up the map so that it may be used.
21269ce434fSBarry Smith 
213d083f849SBarry Smith   Collective
21469ce434fSBarry Smith 
21569ce434fSBarry Smith   Input Parameters:
21669ce434fSBarry Smith . map - pointer to the map
21769ce434fSBarry Smith 
21869ce434fSBarry Smith   Level: developer
21969ce434fSBarry Smith 
22095452b02SPatrick Sanan   Notes:
22195452b02SPatrick Sanan     Typical calling sequence
222c3002683SMatthew G. Knepley $ PetscLayoutCreate(MPI_Comm,PetscLayout *);
223c3002683SMatthew G. Knepley $ PetscLayoutSetBlockSize(PetscLayout,1);
224c3002683SMatthew G. Knepley $ PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both
225c3002683SMatthew G. Knepley $ PetscLayoutSetUp(PetscLayout);
226c3002683SMatthew G. Knepley $ PetscLayoutGetSize(PetscLayout,PetscInt *);
22769ce434fSBarry Smith 
2287b659617SVaclav Hapla   If range exists, and local size is not set, everything gets computed from the range.
22969ce434fSBarry Smith 
23069ce434fSBarry Smith   If the local size, global size are already set and range exists then this does nothing.
23169ce434fSBarry Smith 
23269ce434fSBarry Smith .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
23369ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutCreate()
23469ce434fSBarry Smith @*/
23569ce434fSBarry Smith PetscErrorCode PetscLayoutSetUp(PetscLayout map)
23669ce434fSBarry Smith {
23769ce434fSBarry Smith   PetscMPIInt    rank,size;
23869ce434fSBarry Smith   PetscInt       p;
23969ce434fSBarry Smith   PetscErrorCode ierr;
24069ce434fSBarry Smith 
24169ce434fSBarry Smith   PetscFunctionBegin;
24269ce434fSBarry Smith   if ((map->n >= 0) && (map->N >= 0) && (map->range)) PetscFunctionReturn(0);
24369ce434fSBarry Smith 
244b146b01cSBarry Smith   if (map->n > 0 && map->bs > 1) {
245ec4d677dSStefano Zampini     if (map->n % map->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local size %D must be divisible by blocksize %D",map->n,map->bs);
246b146b01cSBarry Smith   }
247b146b01cSBarry Smith   if (map->N > 0 && map->bs > 1) {
248ec4d677dSStefano Zampini     if (map->N % map->bs) SETERRQ2(map->comm,PETSC_ERR_PLIB,"Global size %D must be divisible by blocksize %D",map->N,map->bs);
249b146b01cSBarry Smith   }
250b146b01cSBarry Smith 
25169ce434fSBarry Smith   ierr = MPI_Comm_size(map->comm, &size);CHKERRQ(ierr);
25269ce434fSBarry Smith   ierr = MPI_Comm_rank(map->comm, &rank);CHKERRQ(ierr);
25333d57670SJed Brown   if (map->n > 0) map->n = map->n/PetscAbs(map->bs);
25433d57670SJed Brown   if (map->N > 0) map->N = map->N/PetscAbs(map->bs);
25569ce434fSBarry Smith   ierr = PetscSplitOwnership(map->comm,&map->n,&map->N);CHKERRQ(ierr);
25633d57670SJed Brown   map->n = map->n*PetscAbs(map->bs);
25733d57670SJed Brown   map->N = map->N*PetscAbs(map->bs);
25869ce434fSBarry Smith   if (!map->range) {
259854ce69bSBarry Smith     ierr = PetscMalloc1(size+1, &map->range);CHKERRQ(ierr);
26069ce434fSBarry Smith   }
26169ce434fSBarry Smith   ierr = MPI_Allgather(&map->n, 1, MPIU_INT, map->range+1, 1, MPIU_INT, map->comm);CHKERRQ(ierr);
26269ce434fSBarry Smith 
26369ce434fSBarry Smith   map->range[0] = 0;
26469ce434fSBarry Smith   for (p = 2; p <= size; p++) map->range[p] += map->range[p-1];
26569ce434fSBarry Smith 
26669ce434fSBarry Smith   map->rstart = map->range[rank];
26769ce434fSBarry Smith   map->rend   = map->range[rank+1];
26869ce434fSBarry Smith   PetscFunctionReturn(0);
26969ce434fSBarry Smith }
27069ce434fSBarry Smith 
271c3002683SMatthew G. Knepley /*@
27269ce434fSBarry Smith   PetscLayoutDuplicate - creates a new PetscLayout with the same information as a given one. If the PetscLayout already exists it is destroyed first.
27369ce434fSBarry Smith 
27469ce434fSBarry Smith   Collective on PetscLayout
27569ce434fSBarry Smith 
27669ce434fSBarry Smith   Input Parameter:
27769ce434fSBarry Smith . in - input PetscLayout to be duplicated
27869ce434fSBarry Smith 
27969ce434fSBarry Smith   Output Parameter:
28069ce434fSBarry Smith . out - the copy
28169ce434fSBarry Smith 
28269ce434fSBarry Smith   Level: developer
28369ce434fSBarry Smith 
28495452b02SPatrick Sanan   Notes:
28595452b02SPatrick Sanan     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
28669ce434fSBarry Smith 
28769ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutReference()
28869ce434fSBarry Smith @*/
28969ce434fSBarry Smith PetscErrorCode PetscLayoutDuplicate(PetscLayout in,PetscLayout *out)
29069ce434fSBarry Smith {
29169ce434fSBarry Smith   PetscMPIInt    size;
29269ce434fSBarry Smith   PetscErrorCode ierr;
29369ce434fSBarry Smith   MPI_Comm       comm = in->comm;
29469ce434fSBarry Smith 
29569ce434fSBarry Smith   PetscFunctionBegin;
29669ce434fSBarry Smith   ierr = PetscLayoutDestroy(out);CHKERRQ(ierr);
29769ce434fSBarry Smith   ierr = PetscLayoutCreate(comm,out);CHKERRQ(ierr);
29869ce434fSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
29969ce434fSBarry Smith   ierr = PetscMemcpy(*out,in,sizeof(struct _n_PetscLayout));CHKERRQ(ierr);
300c168f6d8SVaclav Hapla   if (in->range) {
301854ce69bSBarry Smith     ierr = PetscMalloc1(size+1,&(*out)->range);CHKERRQ(ierr);
302580bdb30SBarry Smith     ierr = PetscArraycpy((*out)->range,in->range,size+1);CHKERRQ(ierr);
303c168f6d8SVaclav Hapla   }
30469ce434fSBarry Smith 
30569ce434fSBarry Smith   (*out)->refcnt = 0;
30669ce434fSBarry Smith   PetscFunctionReturn(0);
30769ce434fSBarry Smith }
30869ce434fSBarry Smith 
309c3002683SMatthew G. Knepley /*@
31069ce434fSBarry Smith   PetscLayoutReference - Causes a PETSc Vec or Mat to share a PetscLayout with one that already exists. Used by Vec/MatDuplicate_XXX()
31169ce434fSBarry Smith 
31269ce434fSBarry Smith   Collective on PetscLayout
31369ce434fSBarry Smith 
31469ce434fSBarry Smith   Input Parameter:
31569ce434fSBarry Smith . in - input PetscLayout to be copied
31669ce434fSBarry Smith 
31769ce434fSBarry Smith   Output Parameter:
31869ce434fSBarry Smith . out - the reference location
31969ce434fSBarry Smith 
32069ce434fSBarry Smith   Level: developer
32169ce434fSBarry Smith 
32295452b02SPatrick Sanan   Notes:
32395452b02SPatrick Sanan     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
32469ce434fSBarry Smith 
32569ce434fSBarry Smith   If the out location already contains a PetscLayout it is destroyed
32669ce434fSBarry Smith 
32769ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
32869ce434fSBarry Smith @*/
32969ce434fSBarry Smith PetscErrorCode PetscLayoutReference(PetscLayout in,PetscLayout *out)
33069ce434fSBarry Smith {
33169ce434fSBarry Smith   PetscErrorCode ierr;
33269ce434fSBarry Smith 
33369ce434fSBarry Smith   PetscFunctionBegin;
33469ce434fSBarry Smith   in->refcnt++;
33569ce434fSBarry Smith   ierr = PetscLayoutDestroy(out);CHKERRQ(ierr);
33669ce434fSBarry Smith   *out = in;
33769ce434fSBarry Smith   PetscFunctionReturn(0);
33869ce434fSBarry Smith }
33969ce434fSBarry Smith 
340c3002683SMatthew G. Knepley /*@
34169ce434fSBarry Smith   PetscLayoutSetISLocalToGlobalMapping - sets a ISLocalGlobalMapping into a PetscLayout
34269ce434fSBarry Smith 
34369ce434fSBarry Smith   Collective on PetscLayout
34469ce434fSBarry Smith 
34569ce434fSBarry Smith   Input Parameter:
34669ce434fSBarry Smith + in - input PetscLayout
34769ce434fSBarry Smith - ltog - the local to global mapping
34869ce434fSBarry Smith 
34969ce434fSBarry Smith 
35069ce434fSBarry Smith   Level: developer
35169ce434fSBarry Smith 
35295452b02SPatrick Sanan   Notes:
35395452b02SPatrick Sanan     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
35469ce434fSBarry Smith 
35569ce434fSBarry Smith   If the ltog location already contains a PetscLayout it is destroyed
35669ce434fSBarry Smith 
357a188d78dSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
35869ce434fSBarry Smith @*/
35969ce434fSBarry Smith PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in,ISLocalToGlobalMapping ltog)
36069ce434fSBarry Smith {
36169ce434fSBarry Smith   PetscErrorCode ierr;
36245b6f7e9SBarry Smith   PetscInt       bs;
36369ce434fSBarry Smith 
36469ce434fSBarry Smith   PetscFunctionBegin;
36545b6f7e9SBarry Smith   ierr = ISLocalToGlobalMappingGetBlockSize(ltog,&bs);CHKERRQ(ierr);
36637461477SLawrence Mitchell   if (in->bs > 0 && (bs != 1) && in->bs != bs) SETERRQ2(in->comm,PETSC_ERR_PLIB,"Blocksize of layout %D must match that of mapping %D (or the latter must be 1)",in->bs,bs);
36769ce434fSBarry Smith   ierr = PetscObjectReference((PetscObject)ltog);CHKERRQ(ierr);
36869ce434fSBarry Smith   ierr = ISLocalToGlobalMappingDestroy(&in->mapping);CHKERRQ(ierr);
36969ce434fSBarry Smith   in->mapping = ltog;
37069ce434fSBarry Smith   PetscFunctionReturn(0);
37169ce434fSBarry Smith }
37269ce434fSBarry Smith 
373c3002683SMatthew G. Knepley /*@
37469ce434fSBarry Smith   PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object.
37569ce434fSBarry Smith 
37669ce434fSBarry Smith   Collective on PetscLayout
37769ce434fSBarry Smith 
37869ce434fSBarry Smith   Input Parameters:
37969ce434fSBarry Smith + map - pointer to the map
38069ce434fSBarry Smith - n - the local size
38169ce434fSBarry Smith 
38269ce434fSBarry Smith   Level: developer
38369ce434fSBarry Smith 
38469ce434fSBarry Smith   Notes:
38569ce434fSBarry Smith   Call this after the call to PetscLayoutCreate()
38669ce434fSBarry Smith 
38769ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
38869ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
38969ce434fSBarry Smith @*/
39069ce434fSBarry Smith PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map,PetscInt n)
39169ce434fSBarry Smith {
39269ce434fSBarry Smith   PetscFunctionBegin;
39369ce434fSBarry Smith   if (map->bs > 1 && n % map->bs) SETERRQ2(map->comm,PETSC_ERR_ARG_INCOMP,"Local size %D not compatible with block size %D",n,map->bs);
39469ce434fSBarry Smith   map->n = n;
39569ce434fSBarry Smith   PetscFunctionReturn(0);
39669ce434fSBarry Smith }
39769ce434fSBarry Smith 
39869ce434fSBarry Smith /*@C
39969ce434fSBarry Smith      PetscLayoutGetLocalSize - Gets the local size for a PetscLayout object.
40069ce434fSBarry Smith 
40169ce434fSBarry Smith     Not Collective
40269ce434fSBarry Smith 
40369ce434fSBarry Smith    Input Parameters:
40469ce434fSBarry Smith .    map - pointer to the map
40569ce434fSBarry Smith 
40669ce434fSBarry Smith    Output Parameters:
40769ce434fSBarry Smith .    n - the local size
40869ce434fSBarry Smith 
40969ce434fSBarry Smith    Level: developer
41069ce434fSBarry Smith 
41169ce434fSBarry Smith     Notes:
41269ce434fSBarry Smith        Call this after the call to PetscLayoutSetUp()
41369ce434fSBarry Smith 
41469ce434fSBarry Smith     Fortran Notes:
41569ce434fSBarry Smith       Not available from Fortran
41669ce434fSBarry Smith 
41769ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
41869ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
41969ce434fSBarry Smith 
42069ce434fSBarry Smith @*/
42169ce434fSBarry Smith PetscErrorCode  PetscLayoutGetLocalSize(PetscLayout map,PetscInt *n)
42269ce434fSBarry Smith {
42369ce434fSBarry Smith   PetscFunctionBegin;
42469ce434fSBarry Smith   *n = map->n;
42569ce434fSBarry Smith   PetscFunctionReturn(0);
42669ce434fSBarry Smith }
42769ce434fSBarry Smith 
428c3002683SMatthew G. Knepley /*@
42969ce434fSBarry Smith   PetscLayoutSetSize - Sets the global size for a PetscLayout object.
43069ce434fSBarry Smith 
43169ce434fSBarry Smith   Logically Collective on PetscLayout
43269ce434fSBarry Smith 
43369ce434fSBarry Smith   Input Parameters:
43469ce434fSBarry Smith + map - pointer to the map
43569ce434fSBarry Smith - n - the global size
43669ce434fSBarry Smith 
43769ce434fSBarry Smith   Level: developer
43869ce434fSBarry Smith 
43969ce434fSBarry Smith   Notes:
44069ce434fSBarry Smith   Call this after the call to PetscLayoutCreate()
44169ce434fSBarry Smith 
44269ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
44369ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
44469ce434fSBarry Smith @*/
44569ce434fSBarry Smith PetscErrorCode PetscLayoutSetSize(PetscLayout map,PetscInt n)
44669ce434fSBarry Smith {
44769ce434fSBarry Smith   PetscFunctionBegin;
44869ce434fSBarry Smith   map->N = n;
44969ce434fSBarry Smith   PetscFunctionReturn(0);
45069ce434fSBarry Smith }
45169ce434fSBarry Smith 
452c3002683SMatthew G. Knepley /*@
45369ce434fSBarry Smith   PetscLayoutGetSize - Gets the global size for a PetscLayout object.
45469ce434fSBarry Smith 
45569ce434fSBarry Smith   Not Collective
45669ce434fSBarry Smith 
45769ce434fSBarry Smith   Input Parameters:
45869ce434fSBarry Smith . map - pointer to the map
45969ce434fSBarry Smith 
46069ce434fSBarry Smith   Output Parameters:
46169ce434fSBarry Smith . n - the global size
46269ce434fSBarry Smith 
46369ce434fSBarry Smith   Level: developer
46469ce434fSBarry Smith 
46569ce434fSBarry Smith   Notes:
46669ce434fSBarry Smith   Call this after the call to PetscLayoutSetUp()
46769ce434fSBarry Smith 
46869ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
46969ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
47069ce434fSBarry Smith @*/
47169ce434fSBarry Smith PetscErrorCode PetscLayoutGetSize(PetscLayout map,PetscInt *n)
47269ce434fSBarry Smith {
47369ce434fSBarry Smith   PetscFunctionBegin;
47469ce434fSBarry Smith   *n = map->N;
47569ce434fSBarry Smith   PetscFunctionReturn(0);
47669ce434fSBarry Smith }
47769ce434fSBarry Smith 
478c3002683SMatthew G. Knepley /*@
47969ce434fSBarry Smith   PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object.
48069ce434fSBarry Smith 
48169ce434fSBarry Smith   Logically Collective on PetscLayout
48269ce434fSBarry Smith 
48369ce434fSBarry Smith   Input Parameters:
48469ce434fSBarry Smith + map - pointer to the map
48569ce434fSBarry Smith - bs - the size
48669ce434fSBarry Smith 
48769ce434fSBarry Smith   Level: developer
48869ce434fSBarry Smith 
48969ce434fSBarry Smith   Notes:
49069ce434fSBarry Smith   Call this after the call to PetscLayoutCreate()
49169ce434fSBarry Smith 
49269ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
49369ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
49469ce434fSBarry Smith @*/
49569ce434fSBarry Smith PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs)
49669ce434fSBarry Smith {
49769ce434fSBarry Smith   PetscFunctionBegin;
49869bbac97SJed Brown   if (bs < 0) PetscFunctionReturn(0);
499299e779cSStefano Zampini   if (map->n > 0 && map->n % bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local size %D not compatible with block size %D",map->n,bs);
500565245c5SBarry Smith   if (map->mapping) {
501705e6b8bSstefano_zampini     PetscInt       obs;
502565245c5SBarry Smith     PetscErrorCode ierr;
503565245c5SBarry Smith 
504705e6b8bSstefano_zampini     ierr = ISLocalToGlobalMappingGetBlockSize(map->mapping,&obs);CHKERRQ(ierr);
505705e6b8bSstefano_zampini     if (obs > 1) {
50663fa5c83Sstefano_zampini       ierr = ISLocalToGlobalMappingSetBlockSize(map->mapping,bs);CHKERRQ(ierr);
507565245c5SBarry Smith     }
508705e6b8bSstefano_zampini   }
50969ce434fSBarry Smith   map->bs = bs;
51069ce434fSBarry Smith   PetscFunctionReturn(0);
51169ce434fSBarry Smith }
51269ce434fSBarry Smith 
513c3002683SMatthew G. Knepley /*@
51469ce434fSBarry Smith   PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object.
51569ce434fSBarry Smith 
51669ce434fSBarry Smith   Not Collective
51769ce434fSBarry Smith 
51869ce434fSBarry Smith   Input Parameters:
51969ce434fSBarry Smith . map - pointer to the map
52069ce434fSBarry Smith 
52169ce434fSBarry Smith   Output Parameters:
52269ce434fSBarry Smith . bs - the size
52369ce434fSBarry Smith 
52469ce434fSBarry Smith   Level: developer
52569ce434fSBarry Smith 
52669ce434fSBarry Smith   Notes:
52769ce434fSBarry Smith   Call this after the call to PetscLayoutSetUp()
52869ce434fSBarry Smith 
52969ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
53069ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize()
53169ce434fSBarry Smith @*/
53269ce434fSBarry Smith PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs)
53369ce434fSBarry Smith {
53469ce434fSBarry Smith   PetscFunctionBegin;
53533d57670SJed Brown   *bs = PetscAbs(map->bs);
53669ce434fSBarry Smith   PetscFunctionReturn(0);
53769ce434fSBarry Smith }
53869ce434fSBarry Smith 
539c3002683SMatthew G. Knepley /*@
54069ce434fSBarry Smith   PetscLayoutGetRange - gets the range of values owned by this process
54169ce434fSBarry Smith 
54269ce434fSBarry Smith   Not Collective
54369ce434fSBarry Smith 
54469ce434fSBarry Smith   Input Parameters:
54569ce434fSBarry Smith . map - pointer to the map
54669ce434fSBarry Smith 
54769ce434fSBarry Smith   Output Parameters:
54869ce434fSBarry Smith + rstart - first index owned by this process
54969ce434fSBarry Smith - rend   - one more than the last index owned by this process
55069ce434fSBarry Smith 
55169ce434fSBarry Smith   Level: developer
55269ce434fSBarry Smith 
55369ce434fSBarry Smith   Notes:
55469ce434fSBarry Smith   Call this after the call to PetscLayoutSetUp()
55569ce434fSBarry Smith 
55669ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
55769ce434fSBarry Smith           PetscLayoutGetSize(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
55869ce434fSBarry Smith @*/
55969ce434fSBarry Smith PetscErrorCode PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend)
56069ce434fSBarry Smith {
56169ce434fSBarry Smith   PetscFunctionBegin;
56269ce434fSBarry Smith   if (rstart) *rstart = map->rstart;
56369ce434fSBarry Smith   if (rend)   *rend   = map->rend;
56469ce434fSBarry Smith   PetscFunctionReturn(0);
56569ce434fSBarry Smith }
56669ce434fSBarry Smith 
56769ce434fSBarry Smith /*@C
56869ce434fSBarry Smith      PetscLayoutGetRanges - gets the range of values owned by all processes
56969ce434fSBarry Smith 
57069ce434fSBarry Smith     Not Collective
57169ce434fSBarry Smith 
57269ce434fSBarry Smith    Input Parameters:
57369ce434fSBarry Smith .    map - pointer to the map
57469ce434fSBarry Smith 
57569ce434fSBarry Smith    Output Parameters:
57669ce434fSBarry Smith .    range - start of each processors range of indices (the final entry is one more then the
57769ce434fSBarry Smith              last index on the last process)
57869ce434fSBarry Smith 
57969ce434fSBarry Smith    Level: developer
58069ce434fSBarry Smith 
58169ce434fSBarry Smith     Notes:
58269ce434fSBarry Smith        Call this after the call to PetscLayoutSetUp()
58369ce434fSBarry Smith 
58469ce434fSBarry Smith     Fortran Notes:
58569ce434fSBarry Smith       Not available from Fortran
58669ce434fSBarry Smith 
58769ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
58869ce434fSBarry Smith           PetscLayoutGetSize(), PetscLayoutGetRange(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
58969ce434fSBarry Smith 
59069ce434fSBarry Smith @*/
59169ce434fSBarry Smith PetscErrorCode  PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[])
59269ce434fSBarry Smith {
59369ce434fSBarry Smith   PetscFunctionBegin;
59469ce434fSBarry Smith   *range = map->range;
59569ce434fSBarry Smith   PetscFunctionReturn(0);
59669ce434fSBarry Smith }
59769ce434fSBarry Smith 
59869ce434fSBarry Smith /*@C
59969ce434fSBarry Smith    PetscSFSetGraphLayout - Set a parallel star forest via global indices and a PetscLayout
60069ce434fSBarry Smith 
60169ce434fSBarry Smith    Collective
60269ce434fSBarry Smith 
60369ce434fSBarry Smith    Input Arguments:
60469ce434fSBarry Smith +  sf - star forest
60569ce434fSBarry Smith .  layout - PetscLayout defining the global space
60669ce434fSBarry Smith .  nleaves - number of leaf vertices on the current process, each of these references a root on any process
60769ce434fSBarry Smith .  ilocal - locations of leaves in leafdata buffers, pass NULL for contiguous storage
608cf79137fSStefano Zampini .  localmode - copy mode for ilocal
60969ce434fSBarry Smith -  iremote - remote locations of root vertices for each leaf on the current process
61069ce434fSBarry Smith 
61169ce434fSBarry Smith    Level: intermediate
61269ce434fSBarry Smith 
613cf79137fSStefano Zampini    Developers Note: Local indices which are the identity permutation in the range [0,nleaves) are discarded as they
614cf79137fSStefano Zampini    encode contiguous storage. In such case, if localmode is PETSC_OWN_POINTER, the memory is deallocated as it is not
615cf79137fSStefano Zampini    needed
616cf79137fSStefano Zampini 
61769ce434fSBarry Smith .seealso: PetscSFCreate(), PetscSFView(), PetscSFSetGraph(), PetscSFGetGraph()
61869ce434fSBarry Smith @*/
61969ce434fSBarry Smith PetscErrorCode PetscSFSetGraphLayout(PetscSF sf,PetscLayout layout,PetscInt nleaves,const PetscInt *ilocal,PetscCopyMode localmode,const PetscInt *iremote)
62069ce434fSBarry Smith {
62169ce434fSBarry Smith   PetscErrorCode ierr;
62269ce434fSBarry Smith   PetscInt       i,nroots;
62369ce434fSBarry Smith   PetscSFNode    *remote;
62469ce434fSBarry Smith 
62569ce434fSBarry Smith   PetscFunctionBegin;
62669ce434fSBarry Smith   ierr = PetscLayoutGetLocalSize(layout,&nroots);CHKERRQ(ierr);
627785e854fSJed Brown   ierr = PetscMalloc1(nleaves,&remote);CHKERRQ(ierr);
62869ce434fSBarry Smith   for (i=0; i<nleaves; i++) {
62969ce434fSBarry Smith     PetscInt owner = -1;
63069ce434fSBarry Smith     ierr = PetscLayoutFindOwner(layout,iremote[i],&owner);CHKERRQ(ierr);
63169ce434fSBarry Smith     remote[i].rank  = owner;
63269ce434fSBarry Smith     remote[i].index = iremote[i] - layout->range[owner];
63369ce434fSBarry Smith   }
63469ce434fSBarry Smith   ierr = PetscSFSetGraph(sf,nroots,nleaves,ilocal,localmode,remote,PETSC_OWN_POINTER);CHKERRQ(ierr);
63569ce434fSBarry Smith   PetscFunctionReturn(0);
63669ce434fSBarry Smith }
63769ce434fSBarry Smith 
638f92d6284SStefano Zampini /*@
639f92d6284SStefano Zampini   PetscLayoutCompare - Compares two layouts
640f92d6284SStefano Zampini 
641f92d6284SStefano Zampini   Not Collective
642f92d6284SStefano Zampini 
643f92d6284SStefano Zampini   Input Parameters:
644d11c674dSStefano Zampini + mapa - pointer to the first map
645f92d6284SStefano Zampini - mapb - pointer to the second map
646f92d6284SStefano Zampini 
647f92d6284SStefano Zampini   Output Parameters:
648f92d6284SStefano Zampini . congruent - PETSC_TRUE if the two layouts are congruent, PETSC_FALSE otherwise
649f92d6284SStefano Zampini 
650f92d6284SStefano Zampini   Level: beginner
651f92d6284SStefano Zampini 
652f92d6284SStefano Zampini   Notes:
653f92d6284SStefano Zampini 
654f92d6284SStefano Zampini .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
655f92d6284SStefano Zampini           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
656f92d6284SStefano Zampini @*/
657f92d6284SStefano Zampini PetscErrorCode PetscLayoutCompare(PetscLayout mapa,PetscLayout mapb,PetscBool *congruent)
658f92d6284SStefano Zampini {
659f92d6284SStefano Zampini   PetscErrorCode ierr;
660f92d6284SStefano Zampini   PetscMPIInt    sizea,sizeb;
661f92d6284SStefano Zampini 
662f92d6284SStefano Zampini   PetscFunctionBegin;
663f92d6284SStefano Zampini   *congruent = PETSC_FALSE;
664f92d6284SStefano Zampini   ierr = MPI_Comm_size(mapa->comm,&sizea);CHKERRQ(ierr);
665f92d6284SStefano Zampini   ierr = MPI_Comm_size(mapb->comm,&sizeb);CHKERRQ(ierr);
666f92d6284SStefano Zampini   if (mapa->N == mapb->N && mapa->range && mapb->range && sizea == sizeb) {
667580bdb30SBarry Smith     ierr = PetscArraycmp(mapa->range,mapb->range,sizea+1,congruent);CHKERRQ(ierr);
668f92d6284SStefano Zampini   }
669f92d6284SStefano Zampini   PetscFunctionReturn(0);
670f92d6284SStefano Zampini }
671a72d46e8SStefano Zampini 
672a72d46e8SStefano Zampini /* TODO: handle nooffprocentries like MatZeroRowsMapLocal_Private, since this code is the same */
673a72d46e8SStefano Zampini PetscErrorCode PetscLayoutMapLocal(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
674a72d46e8SStefano Zampini {
675a72d46e8SStefano Zampini   PetscInt      *owners = map->range;
676a72d46e8SStefano Zampini   PetscInt       n      = map->n;
677a72d46e8SStefano Zampini   PetscSF        sf;
678a72d46e8SStefano Zampini   PetscInt      *lidxs,*work = NULL;
679a72d46e8SStefano Zampini   PetscSFNode   *ridxs;
680a72d46e8SStefano Zampini   PetscMPIInt    rank;
681a72d46e8SStefano Zampini   PetscInt       r, p = 0, len = 0;
682a72d46e8SStefano Zampini   PetscErrorCode ierr;
683a72d46e8SStefano Zampini 
684a72d46e8SStefano Zampini   PetscFunctionBegin;
685a72d46e8SStefano Zampini   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
686a72d46e8SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs */
687a72d46e8SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
688a72d46e8SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
689a72d46e8SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
690a72d46e8SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
691a72d46e8SStefano Zampini   for (r = 0; r < N; ++r) {
692a72d46e8SStefano Zampini     const PetscInt idx = idxs[r];
693a72d46e8SStefano Zampini     if (idx < 0 || map->N <= idx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Index %D out of range [0,%D)",idx,map->N);
694a72d46e8SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
695a72d46e8SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
696a72d46e8SStefano Zampini     }
697a72d46e8SStefano Zampini     ridxs[r].rank = p;
698a72d46e8SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
699a72d46e8SStefano Zampini   }
700a72d46e8SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
701a72d46e8SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
702a72d46e8SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
703a72d46e8SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
704a72d46e8SStefano Zampini   if (ogidxs) { /* communicate global idxs */
705a72d46e8SStefano Zampini     PetscInt cum = 0,start,*work2;
706a72d46e8SStefano Zampini 
707a72d46e8SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
708a72d46e8SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
709a72d46e8SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
710a72d46e8SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
711a72d46e8SStefano Zampini     start -= cum;
712a72d46e8SStefano Zampini     cum = 0;
713a72d46e8SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
714a72d46e8SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
715a72d46e8SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
716a72d46e8SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
717a72d46e8SStefano Zampini   }
718a72d46e8SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
719a72d46e8SStefano Zampini   /* Compress and put in indices */
720a72d46e8SStefano Zampini   for (r = 0; r < n; ++r)
721a72d46e8SStefano Zampini     if (lidxs[r] >= 0) {
722a72d46e8SStefano Zampini       if (work) work[len] = work[r];
723a72d46e8SStefano Zampini       lidxs[len++] = r;
724a72d46e8SStefano Zampini     }
725a72d46e8SStefano Zampini   if (on) *on = len;
726a72d46e8SStefano Zampini   if (oidxs) *oidxs = lidxs;
727a72d46e8SStefano Zampini   if (ogidxs) *ogidxs = work;
728a72d46e8SStefano Zampini   PetscFunctionReturn(0);
729a72d46e8SStefano Zampini }
730