xref: /petsc/src/vec/is/utils/pmap.c (revision f0fc11cebb1bb284829732915f9e84cabc170c2f)
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
319621ec18SVaclav Hapla   Alternatively,
329621ec18SVaclav Hapla $      PetscLayoutCreateFromSizes(comm,n,N,bs,&layout);
339621ec18SVaclav 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(),
469621ec18SVaclav Hapla           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp(),
479621ec18SVaclav 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;
629621ec18SVaclav Hapla   (*map)->range_alloc = PETSC_TRUE;
6369ce434fSBarry Smith   (*map)->rstart      = 0;
6469ce434fSBarry Smith   (*map)->rend        = 0;
65ca5434daSLawrence Mitchell   (*map)->setupcalled = PETSC_FALSE;
66ca5434daSLawrence Mitchell   (*map)->oldn        = -1;
67ca5434daSLawrence Mitchell   (*map)->oldN        = -1;
68ca5434daSLawrence Mitchell   (*map)->oldbs       = -1;
6969ce434fSBarry Smith   PetscFunctionReturn(0);
7069ce434fSBarry Smith }
7169ce434fSBarry Smith 
72c3002683SMatthew G. Knepley /*@
739621ec18SVaclav Hapla   PetscLayoutCreateFromSizes - Allocates PetscLayout space, sets the layout sizes, and sets the layout up.
749621ec18SVaclav Hapla 
759621ec18SVaclav Hapla   Collective
769621ec18SVaclav Hapla 
779621ec18SVaclav Hapla   Input Parameters:
789621ec18SVaclav Hapla + comm  - the MPI communicator
799621ec18SVaclav Hapla . n     - the local size (or PETSC_DECIDE)
809621ec18SVaclav Hapla . N     - the global size (or PETSC_DECIDE)
81*f0fc11ceSJed Brown - bs    - the block size (or PETSC_DECIDE)
829621ec18SVaclav Hapla 
839621ec18SVaclav Hapla   Output Parameters:
849621ec18SVaclav Hapla . map - the new PetscLayout
859621ec18SVaclav Hapla 
869621ec18SVaclav Hapla   Level: advanced
879621ec18SVaclav Hapla 
889621ec18SVaclav Hapla   Notes:
899621ec18SVaclav Hapla $ PetscLayoutCreateFromSizes(comm,n,N,bs,&layout);
909621ec18SVaclav Hapla   is a shorthand for
919621ec18SVaclav Hapla .vb
929621ec18SVaclav Hapla   PetscLayoutCreate(comm,&layout);
939621ec18SVaclav Hapla   PetscLayoutSetLocalSize(layout,n);
949621ec18SVaclav Hapla   PetscLayoutSetSize(layout,N);
959621ec18SVaclav Hapla   PetscLayoutSetBlockSize(layout,bs);
969621ec18SVaclav Hapla   PetscLayoutSetUp(layout);
979621ec18SVaclav Hapla .ve
989621ec18SVaclav Hapla 
999621ec18SVaclav Hapla .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
1009621ec18SVaclav Hapla           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp(), PetscLayoutCreateFromRanges()
1019621ec18SVaclav Hapla 
1029621ec18SVaclav Hapla @*/
1039621ec18SVaclav Hapla PetscErrorCode PetscLayoutCreateFromSizes(MPI_Comm comm,PetscInt n,PetscInt N,PetscInt bs,PetscLayout *map)
1049621ec18SVaclav Hapla {
1059621ec18SVaclav Hapla   PetscErrorCode ierr;
1069621ec18SVaclav Hapla 
1079621ec18SVaclav Hapla   PetscFunctionBegin;
1089621ec18SVaclav Hapla   ierr = PetscLayoutCreate(comm, map);CHKERRQ(ierr);
1099621ec18SVaclav Hapla   ierr = PetscLayoutSetLocalSize(*map, n);CHKERRQ(ierr);
1109621ec18SVaclav Hapla   ierr = PetscLayoutSetSize(*map, N);CHKERRQ(ierr);
1119621ec18SVaclav Hapla   ierr = PetscLayoutSetBlockSize(*map, bs);CHKERRQ(ierr);
1129621ec18SVaclav Hapla   ierr = PetscLayoutSetUp(*map);CHKERRQ(ierr);
1139621ec18SVaclav Hapla   PetscFunctionReturn(0);
1149621ec18SVaclav Hapla }
1159621ec18SVaclav Hapla 
1169621ec18SVaclav Hapla /*@
11769ce434fSBarry Smith   PetscLayoutDestroy - Frees a map object and frees its range if that exists.
11869ce434fSBarry Smith 
119d083f849SBarry Smith   Collective
12069ce434fSBarry Smith 
12169ce434fSBarry Smith   Input Parameters:
12269ce434fSBarry Smith . map - the PetscLayout
12369ce434fSBarry Smith 
12469ce434fSBarry Smith   Level: developer
12569ce434fSBarry Smith 
126c3002683SMatthew G. Knepley   Note:
12769ce434fSBarry Smith   The PetscLayout object and methods are intended to be used in the PETSc Vec and Mat implementions; it is
12869ce434fSBarry Smith   recommended they not be used in user codes unless you really gain something in their use.
12969ce434fSBarry Smith 
13069ce434fSBarry Smith .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutCreate(),
13169ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp()
13269ce434fSBarry Smith 
13369ce434fSBarry Smith @*/
13469ce434fSBarry Smith PetscErrorCode PetscLayoutDestroy(PetscLayout *map)
13569ce434fSBarry Smith {
13669ce434fSBarry Smith   PetscErrorCode ierr;
13769ce434fSBarry Smith 
13869ce434fSBarry Smith   PetscFunctionBegin;
13969ce434fSBarry Smith   if (!*map) PetscFunctionReturn(0);
14069ce434fSBarry Smith   if (!(*map)->refcnt--) {
1419621ec18SVaclav Hapla     if ((*map)->range_alloc) {ierr = PetscFree((*map)->range);CHKERRQ(ierr);}
14269ce434fSBarry Smith     ierr = ISLocalToGlobalMappingDestroy(&(*map)->mapping);CHKERRQ(ierr);
14369ce434fSBarry Smith     ierr = PetscFree((*map));CHKERRQ(ierr);
14469ce434fSBarry Smith   }
14569ce434fSBarry Smith   *map = NULL;
14669ce434fSBarry Smith   PetscFunctionReturn(0);
14769ce434fSBarry Smith }
14869ce434fSBarry Smith 
1499621ec18SVaclav Hapla /*@
1509621ec18SVaclav Hapla   PetscLayoutCreateFromRanges - Creates a new PetscLayout with the given ownership ranges and sets it up.
1519621ec18SVaclav Hapla 
1529621ec18SVaclav Hapla   Collective
1539621ec18SVaclav Hapla 
1549621ec18SVaclav Hapla   Input Parameters:
1559621ec18SVaclav Hapla + comm  - the MPI communicator
1569621ec18SVaclav Hapla . range - the array of ownership ranges for each rank with length commsize+1
1579621ec18SVaclav Hapla . mode  - the copy mode for range
1589621ec18SVaclav Hapla - bs    - the block size (or PETSC_DECIDE)
1599621ec18SVaclav Hapla 
1609621ec18SVaclav Hapla   Output Parameters:
1619621ec18SVaclav Hapla . newmap - the new PetscLayout
1629621ec18SVaclav Hapla 
1639621ec18SVaclav Hapla   Level: developer
1649621ec18SVaclav Hapla 
1659621ec18SVaclav Hapla .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
1669621ec18SVaclav Hapla           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp(), PetscLayoutCreateFromSizes()
1679621ec18SVaclav Hapla 
1689621ec18SVaclav Hapla @*/
1699621ec18SVaclav Hapla PetscErrorCode PetscLayoutCreateFromRanges(MPI_Comm comm,const PetscInt range[],PetscCopyMode mode,PetscInt bs,PetscLayout *newmap)
1707b659617SVaclav Hapla {
1719621ec18SVaclav Hapla   PetscLayout    map;
1727b659617SVaclav Hapla   PetscMPIInt    rank,size;
1737b659617SVaclav Hapla   PetscErrorCode ierr;
1747b659617SVaclav Hapla 
1757b659617SVaclav Hapla   PetscFunctionBegin;
1769621ec18SVaclav Hapla   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
1779621ec18SVaclav Hapla   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
1789621ec18SVaclav Hapla   ierr = PetscLayoutCreate(comm, &map);CHKERRQ(ierr);
1799621ec18SVaclav Hapla   ierr = PetscLayoutSetBlockSize(map, bs);CHKERRQ(ierr);
1809621ec18SVaclav Hapla   switch (mode) {
1819621ec18SVaclav Hapla     case PETSC_COPY_VALUES:
1829621ec18SVaclav Hapla       ierr = PetscMalloc1(size+1, &map->range);CHKERRQ(ierr);
1839621ec18SVaclav Hapla       ierr = PetscArraycpy(map->range, range, size+1);CHKERRQ(ierr);
1849621ec18SVaclav Hapla       break;
1859621ec18SVaclav Hapla     case PETSC_USE_POINTER:
1869621ec18SVaclav Hapla       map->range_alloc = PETSC_FALSE;
1879621ec18SVaclav Hapla     default:
1889621ec18SVaclav Hapla       map->range = (PetscInt*) range;
1899621ec18SVaclav Hapla       break;
1909621ec18SVaclav Hapla   }
1917b659617SVaclav Hapla   map->rstart = map->range[rank];
1927b659617SVaclav Hapla   map->rend   = map->range[rank+1];
1937b659617SVaclav Hapla   map->n      = map->rend - map->rstart;
1947b659617SVaclav Hapla   map->N      = map->range[size];
1957b659617SVaclav Hapla #if defined(PETSC_USE_DEBUG)
1967b659617SVaclav Hapla   /* just check that n, N and bs are consistent */
1977b659617SVaclav Hapla   {
1987b659617SVaclav Hapla     PetscInt tmp;
1997b659617SVaclav Hapla     ierr = MPIU_Allreduce(&map->n,&tmp,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
2007b659617SVaclav 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);
2017b659617SVaclav Hapla   }
2027b659617SVaclav Hapla   if (map->bs > 1) {
2037b659617SVaclav 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);
2047b659617SVaclav Hapla   }
2057b659617SVaclav Hapla   if (map->bs > 1) {
2067b659617SVaclav 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);
2077b659617SVaclav Hapla   }
2087b659617SVaclav Hapla #endif
209ca5434daSLawrence Mitchell   /* lock the layout */
210ca5434daSLawrence Mitchell   map->setupcalled = PETSC_TRUE;
211ca5434daSLawrence Mitchell   map->oldn = map->n;
212ca5434daSLawrence Mitchell   map->oldN = map->N;
213ca5434daSLawrence Mitchell   map->oldbs = map->bs;
2149621ec18SVaclav Hapla   *newmap = map;
2157b659617SVaclav Hapla   PetscFunctionReturn(0);
2167b659617SVaclav Hapla }
2177b659617SVaclav Hapla 
218c3002683SMatthew G. Knepley /*@
21969ce434fSBarry Smith   PetscLayoutSetUp - given a map where you have set either the global or local
22069ce434fSBarry Smith                      size sets up the map so that it may be used.
22169ce434fSBarry Smith 
222d083f849SBarry Smith   Collective
22369ce434fSBarry Smith 
22469ce434fSBarry Smith   Input Parameters:
22569ce434fSBarry Smith . map - pointer to the map
22669ce434fSBarry Smith 
22769ce434fSBarry Smith   Level: developer
22869ce434fSBarry Smith 
22995452b02SPatrick Sanan   Notes:
23095452b02SPatrick Sanan     Typical calling sequence
231c3002683SMatthew G. Knepley $ PetscLayoutCreate(MPI_Comm,PetscLayout *);
232c3002683SMatthew G. Knepley $ PetscLayoutSetBlockSize(PetscLayout,1);
233c3002683SMatthew G. Knepley $ PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both
234c3002683SMatthew G. Knepley $ PetscLayoutSetUp(PetscLayout);
235c3002683SMatthew G. Knepley $ PetscLayoutGetSize(PetscLayout,PetscInt *);
23669ce434fSBarry Smith 
2377b659617SVaclav Hapla   If range exists, and local size is not set, everything gets computed from the range.
23869ce434fSBarry Smith 
23969ce434fSBarry Smith   If the local size, global size are already set and range exists then this does nothing.
24069ce434fSBarry Smith 
24169ce434fSBarry Smith .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
24269ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutCreate()
24369ce434fSBarry Smith @*/
24469ce434fSBarry Smith PetscErrorCode PetscLayoutSetUp(PetscLayout map)
24569ce434fSBarry Smith {
24669ce434fSBarry Smith   PetscMPIInt    rank,size;
24769ce434fSBarry Smith   PetscInt       p;
24869ce434fSBarry Smith   PetscErrorCode ierr;
24969ce434fSBarry Smith 
25069ce434fSBarry Smith   PetscFunctionBegin;
251ca5434daSLawrence Mitchell   if (map->setupcalled && (map->n != map->oldn || map->N != map->oldN)) SETERRQ4(map->comm,PETSC_ERR_ARG_WRONGSTATE,"Layout is already setup with (local=%D,global=%D), cannot call setup again with (local=%D,global=%D)", map->oldn, map->oldN, map->n, map->N);
252ca5434daSLawrence Mitchell   if (map->setupcalled) PetscFunctionReturn(0);
25369ce434fSBarry Smith 
254b146b01cSBarry Smith   if (map->n > 0 && map->bs > 1) {
255ec4d677dSStefano 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);
256b146b01cSBarry Smith   }
257b146b01cSBarry Smith   if (map->N > 0 && map->bs > 1) {
258ec4d677dSStefano 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);
259b146b01cSBarry Smith   }
260b146b01cSBarry Smith 
26169ce434fSBarry Smith   ierr = MPI_Comm_size(map->comm, &size);CHKERRQ(ierr);
26269ce434fSBarry Smith   ierr = MPI_Comm_rank(map->comm, &rank);CHKERRQ(ierr);
26333d57670SJed Brown   if (map->n > 0) map->n = map->n/PetscAbs(map->bs);
26433d57670SJed Brown   if (map->N > 0) map->N = map->N/PetscAbs(map->bs);
26569ce434fSBarry Smith   ierr = PetscSplitOwnership(map->comm,&map->n,&map->N);CHKERRQ(ierr);
26633d57670SJed Brown   map->n = map->n*PetscAbs(map->bs);
26733d57670SJed Brown   map->N = map->N*PetscAbs(map->bs);
26869ce434fSBarry Smith   if (!map->range) {
269854ce69bSBarry Smith     ierr = PetscMalloc1(size+1, &map->range);CHKERRQ(ierr);
27069ce434fSBarry Smith   }
27169ce434fSBarry Smith   ierr = MPI_Allgather(&map->n, 1, MPIU_INT, map->range+1, 1, MPIU_INT, map->comm);CHKERRQ(ierr);
27269ce434fSBarry Smith 
27369ce434fSBarry Smith   map->range[0] = 0;
27469ce434fSBarry Smith   for (p = 2; p <= size; p++) map->range[p] += map->range[p-1];
27569ce434fSBarry Smith 
27669ce434fSBarry Smith   map->rstart = map->range[rank];
27769ce434fSBarry Smith   map->rend   = map->range[rank+1];
278ca5434daSLawrence Mitchell 
279ca5434daSLawrence Mitchell   /* lock the layout */
280ca5434daSLawrence Mitchell   map->setupcalled = PETSC_TRUE;
281ca5434daSLawrence Mitchell   map->oldn = map->n;
282ca5434daSLawrence Mitchell   map->oldN = map->N;
283ca5434daSLawrence Mitchell   map->oldbs = map->bs;
28469ce434fSBarry Smith   PetscFunctionReturn(0);
28569ce434fSBarry Smith }
28669ce434fSBarry Smith 
287c3002683SMatthew G. Knepley /*@
28869ce434fSBarry Smith   PetscLayoutDuplicate - creates a new PetscLayout with the same information as a given one. If the PetscLayout already exists it is destroyed first.
28969ce434fSBarry Smith 
29069ce434fSBarry Smith   Collective on PetscLayout
29169ce434fSBarry Smith 
29269ce434fSBarry Smith   Input Parameter:
29369ce434fSBarry Smith . in - input PetscLayout to be duplicated
29469ce434fSBarry Smith 
29569ce434fSBarry Smith   Output Parameter:
29669ce434fSBarry Smith . out - the copy
29769ce434fSBarry Smith 
29869ce434fSBarry Smith   Level: developer
29969ce434fSBarry Smith 
30095452b02SPatrick Sanan   Notes:
30195452b02SPatrick Sanan     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
30269ce434fSBarry Smith 
30369ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutReference()
30469ce434fSBarry Smith @*/
30569ce434fSBarry Smith PetscErrorCode PetscLayoutDuplicate(PetscLayout in,PetscLayout *out)
30669ce434fSBarry Smith {
30769ce434fSBarry Smith   PetscMPIInt    size;
30869ce434fSBarry Smith   PetscErrorCode ierr;
30969ce434fSBarry Smith   MPI_Comm       comm = in->comm;
31069ce434fSBarry Smith 
31169ce434fSBarry Smith   PetscFunctionBegin;
31269ce434fSBarry Smith   ierr = PetscLayoutDestroy(out);CHKERRQ(ierr);
31369ce434fSBarry Smith   ierr = PetscLayoutCreate(comm,out);CHKERRQ(ierr);
31469ce434fSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
31569ce434fSBarry Smith   ierr = PetscMemcpy(*out,in,sizeof(struct _n_PetscLayout));CHKERRQ(ierr);
316c168f6d8SVaclav Hapla   if (in->range) {
317854ce69bSBarry Smith     ierr = PetscMalloc1(size+1,&(*out)->range);CHKERRQ(ierr);
318580bdb30SBarry Smith     ierr = PetscArraycpy((*out)->range,in->range,size+1);CHKERRQ(ierr);
319c168f6d8SVaclav Hapla   }
32069ce434fSBarry Smith 
32169ce434fSBarry Smith   (*out)->refcnt = 0;
32269ce434fSBarry Smith   PetscFunctionReturn(0);
32369ce434fSBarry Smith }
32469ce434fSBarry Smith 
325c3002683SMatthew G. Knepley /*@
32669ce434fSBarry Smith   PetscLayoutReference - Causes a PETSc Vec or Mat to share a PetscLayout with one that already exists. Used by Vec/MatDuplicate_XXX()
32769ce434fSBarry Smith 
32869ce434fSBarry Smith   Collective on PetscLayout
32969ce434fSBarry Smith 
33069ce434fSBarry Smith   Input Parameter:
33169ce434fSBarry Smith . in - input PetscLayout to be copied
33269ce434fSBarry Smith 
33369ce434fSBarry Smith   Output Parameter:
33469ce434fSBarry Smith . out - the reference location
33569ce434fSBarry Smith 
33669ce434fSBarry Smith   Level: developer
33769ce434fSBarry Smith 
33895452b02SPatrick Sanan   Notes:
33995452b02SPatrick Sanan     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
34069ce434fSBarry Smith 
34169ce434fSBarry Smith   If the out location already contains a PetscLayout it is destroyed
34269ce434fSBarry Smith 
34369ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
34469ce434fSBarry Smith @*/
34569ce434fSBarry Smith PetscErrorCode PetscLayoutReference(PetscLayout in,PetscLayout *out)
34669ce434fSBarry Smith {
34769ce434fSBarry Smith   PetscErrorCode ierr;
34869ce434fSBarry Smith 
34969ce434fSBarry Smith   PetscFunctionBegin;
35069ce434fSBarry Smith   in->refcnt++;
35169ce434fSBarry Smith   ierr = PetscLayoutDestroy(out);CHKERRQ(ierr);
35269ce434fSBarry Smith   *out = in;
35369ce434fSBarry Smith   PetscFunctionReturn(0);
35469ce434fSBarry Smith }
35569ce434fSBarry Smith 
356c3002683SMatthew G. Knepley /*@
35769ce434fSBarry Smith   PetscLayoutSetISLocalToGlobalMapping - sets a ISLocalGlobalMapping into a PetscLayout
35869ce434fSBarry Smith 
35969ce434fSBarry Smith   Collective on PetscLayout
36069ce434fSBarry Smith 
36169ce434fSBarry Smith   Input Parameter:
36269ce434fSBarry Smith + in - input PetscLayout
36369ce434fSBarry Smith - ltog - the local to global mapping
36469ce434fSBarry Smith 
36569ce434fSBarry Smith 
36669ce434fSBarry Smith   Level: developer
36769ce434fSBarry Smith 
36895452b02SPatrick Sanan   Notes:
36995452b02SPatrick Sanan     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
37069ce434fSBarry Smith 
37169ce434fSBarry Smith   If the ltog location already contains a PetscLayout it is destroyed
37269ce434fSBarry Smith 
373a188d78dSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
37469ce434fSBarry Smith @*/
37569ce434fSBarry Smith PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in,ISLocalToGlobalMapping ltog)
37669ce434fSBarry Smith {
37769ce434fSBarry Smith   PetscErrorCode ierr;
37845b6f7e9SBarry Smith   PetscInt       bs;
37969ce434fSBarry Smith 
38069ce434fSBarry Smith   PetscFunctionBegin;
38145b6f7e9SBarry Smith   ierr = ISLocalToGlobalMappingGetBlockSize(ltog,&bs);CHKERRQ(ierr);
38237461477SLawrence 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);
38369ce434fSBarry Smith   ierr = PetscObjectReference((PetscObject)ltog);CHKERRQ(ierr);
38469ce434fSBarry Smith   ierr = ISLocalToGlobalMappingDestroy(&in->mapping);CHKERRQ(ierr);
38569ce434fSBarry Smith   in->mapping = ltog;
38669ce434fSBarry Smith   PetscFunctionReturn(0);
38769ce434fSBarry Smith }
38869ce434fSBarry Smith 
389c3002683SMatthew G. Knepley /*@
39069ce434fSBarry Smith   PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object.
39169ce434fSBarry Smith 
39269ce434fSBarry Smith   Collective on PetscLayout
39369ce434fSBarry Smith 
39469ce434fSBarry Smith   Input Parameters:
39569ce434fSBarry Smith + map - pointer to the map
39669ce434fSBarry Smith - n - the local size
39769ce434fSBarry Smith 
39869ce434fSBarry Smith   Level: developer
39969ce434fSBarry Smith 
40069ce434fSBarry Smith   Notes:
40169ce434fSBarry Smith   Call this after the call to PetscLayoutCreate()
40269ce434fSBarry Smith 
40369ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
40469ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
40569ce434fSBarry Smith @*/
40669ce434fSBarry Smith PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map,PetscInt n)
40769ce434fSBarry Smith {
40869ce434fSBarry Smith   PetscFunctionBegin;
40969ce434fSBarry 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);
41069ce434fSBarry Smith   map->n = n;
41169ce434fSBarry Smith   PetscFunctionReturn(0);
41269ce434fSBarry Smith }
41369ce434fSBarry Smith 
41469ce434fSBarry Smith /*@C
41569ce434fSBarry Smith      PetscLayoutGetLocalSize - Gets the local size for a PetscLayout object.
41669ce434fSBarry Smith 
41769ce434fSBarry Smith     Not Collective
41869ce434fSBarry Smith 
41969ce434fSBarry Smith    Input Parameters:
42069ce434fSBarry Smith .    map - pointer to the map
42169ce434fSBarry Smith 
42269ce434fSBarry Smith    Output Parameters:
42369ce434fSBarry Smith .    n - the local size
42469ce434fSBarry Smith 
42569ce434fSBarry Smith    Level: developer
42669ce434fSBarry Smith 
42769ce434fSBarry Smith     Notes:
42869ce434fSBarry Smith        Call this after the call to PetscLayoutSetUp()
42969ce434fSBarry Smith 
43069ce434fSBarry Smith     Fortran Notes:
43169ce434fSBarry Smith       Not available from Fortran
43269ce434fSBarry Smith 
43369ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
43469ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
43569ce434fSBarry Smith 
43669ce434fSBarry Smith @*/
43769ce434fSBarry Smith PetscErrorCode  PetscLayoutGetLocalSize(PetscLayout map,PetscInt *n)
43869ce434fSBarry Smith {
43969ce434fSBarry Smith   PetscFunctionBegin;
44069ce434fSBarry Smith   *n = map->n;
44169ce434fSBarry Smith   PetscFunctionReturn(0);
44269ce434fSBarry Smith }
44369ce434fSBarry Smith 
444c3002683SMatthew G. Knepley /*@
44569ce434fSBarry Smith   PetscLayoutSetSize - Sets the global size for a PetscLayout object.
44669ce434fSBarry Smith 
44769ce434fSBarry Smith   Logically Collective on PetscLayout
44869ce434fSBarry Smith 
44969ce434fSBarry Smith   Input Parameters:
45069ce434fSBarry Smith + map - pointer to the map
45169ce434fSBarry Smith - n - the global size
45269ce434fSBarry Smith 
45369ce434fSBarry Smith   Level: developer
45469ce434fSBarry Smith 
45569ce434fSBarry Smith   Notes:
45669ce434fSBarry Smith   Call this after the call to PetscLayoutCreate()
45769ce434fSBarry Smith 
45869ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
45969ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
46069ce434fSBarry Smith @*/
46169ce434fSBarry Smith PetscErrorCode PetscLayoutSetSize(PetscLayout map,PetscInt n)
46269ce434fSBarry Smith {
46369ce434fSBarry Smith   PetscFunctionBegin;
46469ce434fSBarry Smith   map->N = n;
46569ce434fSBarry Smith   PetscFunctionReturn(0);
46669ce434fSBarry Smith }
46769ce434fSBarry Smith 
468c3002683SMatthew G. Knepley /*@
46969ce434fSBarry Smith   PetscLayoutGetSize - Gets the global size for a PetscLayout object.
47069ce434fSBarry Smith 
47169ce434fSBarry Smith   Not Collective
47269ce434fSBarry Smith 
47369ce434fSBarry Smith   Input Parameters:
47469ce434fSBarry Smith . map - pointer to the map
47569ce434fSBarry Smith 
47669ce434fSBarry Smith   Output Parameters:
47769ce434fSBarry Smith . n - the global size
47869ce434fSBarry Smith 
47969ce434fSBarry Smith   Level: developer
48069ce434fSBarry Smith 
48169ce434fSBarry Smith   Notes:
48269ce434fSBarry Smith   Call this after the call to PetscLayoutSetUp()
48369ce434fSBarry Smith 
48469ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
48569ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
48669ce434fSBarry Smith @*/
48769ce434fSBarry Smith PetscErrorCode PetscLayoutGetSize(PetscLayout map,PetscInt *n)
48869ce434fSBarry Smith {
48969ce434fSBarry Smith   PetscFunctionBegin;
49069ce434fSBarry Smith   *n = map->N;
49169ce434fSBarry Smith   PetscFunctionReturn(0);
49269ce434fSBarry Smith }
49369ce434fSBarry Smith 
494c3002683SMatthew G. Knepley /*@
49569ce434fSBarry Smith   PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object.
49669ce434fSBarry Smith 
49769ce434fSBarry Smith   Logically Collective on PetscLayout
49869ce434fSBarry Smith 
49969ce434fSBarry Smith   Input Parameters:
50069ce434fSBarry Smith + map - pointer to the map
50169ce434fSBarry Smith - bs - the size
50269ce434fSBarry Smith 
50369ce434fSBarry Smith   Level: developer
50469ce434fSBarry Smith 
50569ce434fSBarry Smith   Notes:
50669ce434fSBarry Smith   Call this after the call to PetscLayoutCreate()
50769ce434fSBarry Smith 
50869ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
50969ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
51069ce434fSBarry Smith @*/
51169ce434fSBarry Smith PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs)
51269ce434fSBarry Smith {
51369ce434fSBarry Smith   PetscFunctionBegin;
51469bbac97SJed Brown   if (bs < 0) PetscFunctionReturn(0);
515299e779cSStefano 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);
516565245c5SBarry Smith   if (map->mapping) {
517705e6b8bSstefano_zampini     PetscInt       obs;
518565245c5SBarry Smith     PetscErrorCode ierr;
519565245c5SBarry Smith 
520705e6b8bSstefano_zampini     ierr = ISLocalToGlobalMappingGetBlockSize(map->mapping,&obs);CHKERRQ(ierr);
521705e6b8bSstefano_zampini     if (obs > 1) {
52263fa5c83Sstefano_zampini       ierr = ISLocalToGlobalMappingSetBlockSize(map->mapping,bs);CHKERRQ(ierr);
523565245c5SBarry Smith     }
524705e6b8bSstefano_zampini   }
52569ce434fSBarry Smith   map->bs = bs;
52669ce434fSBarry Smith   PetscFunctionReturn(0);
52769ce434fSBarry Smith }
52869ce434fSBarry Smith 
529c3002683SMatthew G. Knepley /*@
53069ce434fSBarry Smith   PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object.
53169ce434fSBarry Smith 
53269ce434fSBarry Smith   Not Collective
53369ce434fSBarry Smith 
53469ce434fSBarry Smith   Input Parameters:
53569ce434fSBarry Smith . map - pointer to the map
53669ce434fSBarry Smith 
53769ce434fSBarry Smith   Output Parameters:
53869ce434fSBarry Smith . bs - the size
53969ce434fSBarry Smith 
54069ce434fSBarry Smith   Level: developer
54169ce434fSBarry Smith 
54269ce434fSBarry Smith   Notes:
54369ce434fSBarry Smith   Call this after the call to PetscLayoutSetUp()
54469ce434fSBarry Smith 
54569ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
54669ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize()
54769ce434fSBarry Smith @*/
54869ce434fSBarry Smith PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs)
54969ce434fSBarry Smith {
55069ce434fSBarry Smith   PetscFunctionBegin;
55133d57670SJed Brown   *bs = PetscAbs(map->bs);
55269ce434fSBarry Smith   PetscFunctionReturn(0);
55369ce434fSBarry Smith }
55469ce434fSBarry Smith 
555c3002683SMatthew G. Knepley /*@
55669ce434fSBarry Smith   PetscLayoutGetRange - gets the range of values owned by this process
55769ce434fSBarry Smith 
55869ce434fSBarry Smith   Not Collective
55969ce434fSBarry Smith 
56069ce434fSBarry Smith   Input Parameters:
56169ce434fSBarry Smith . map - pointer to the map
56269ce434fSBarry Smith 
56369ce434fSBarry Smith   Output Parameters:
56469ce434fSBarry Smith + rstart - first index owned by this process
56569ce434fSBarry Smith - rend   - one more than the last index owned by this process
56669ce434fSBarry Smith 
56769ce434fSBarry Smith   Level: developer
56869ce434fSBarry Smith 
56969ce434fSBarry Smith   Notes:
57069ce434fSBarry Smith   Call this after the call to PetscLayoutSetUp()
57169ce434fSBarry Smith 
57269ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
57369ce434fSBarry Smith           PetscLayoutGetSize(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
57469ce434fSBarry Smith @*/
57569ce434fSBarry Smith PetscErrorCode PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend)
57669ce434fSBarry Smith {
57769ce434fSBarry Smith   PetscFunctionBegin;
57869ce434fSBarry Smith   if (rstart) *rstart = map->rstart;
57969ce434fSBarry Smith   if (rend)   *rend   = map->rend;
58069ce434fSBarry Smith   PetscFunctionReturn(0);
58169ce434fSBarry Smith }
58269ce434fSBarry Smith 
58369ce434fSBarry Smith /*@C
58469ce434fSBarry Smith      PetscLayoutGetRanges - gets the range of values owned by all processes
58569ce434fSBarry Smith 
58669ce434fSBarry Smith     Not Collective
58769ce434fSBarry Smith 
58869ce434fSBarry Smith    Input Parameters:
58969ce434fSBarry Smith .    map - pointer to the map
59069ce434fSBarry Smith 
59169ce434fSBarry Smith    Output Parameters:
59269ce434fSBarry Smith .    range - start of each processors range of indices (the final entry is one more then the
59369ce434fSBarry Smith              last index on the last process)
59469ce434fSBarry Smith 
59569ce434fSBarry Smith    Level: developer
59669ce434fSBarry Smith 
59769ce434fSBarry Smith     Notes:
59869ce434fSBarry Smith        Call this after the call to PetscLayoutSetUp()
59969ce434fSBarry Smith 
60069ce434fSBarry Smith     Fortran Notes:
60169ce434fSBarry Smith       Not available from Fortran
60269ce434fSBarry Smith 
60369ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
60469ce434fSBarry Smith           PetscLayoutGetSize(), PetscLayoutGetRange(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
60569ce434fSBarry Smith 
60669ce434fSBarry Smith @*/
60769ce434fSBarry Smith PetscErrorCode  PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[])
60869ce434fSBarry Smith {
60969ce434fSBarry Smith   PetscFunctionBegin;
61069ce434fSBarry Smith   *range = map->range;
61169ce434fSBarry Smith   PetscFunctionReturn(0);
61269ce434fSBarry Smith }
61369ce434fSBarry Smith 
61469ce434fSBarry Smith /*@C
61569ce434fSBarry Smith    PetscSFSetGraphLayout - Set a parallel star forest via global indices and a PetscLayout
61669ce434fSBarry Smith 
61769ce434fSBarry Smith    Collective
61869ce434fSBarry Smith 
61969ce434fSBarry Smith    Input Arguments:
62069ce434fSBarry Smith +  sf - star forest
62169ce434fSBarry Smith .  layout - PetscLayout defining the global space
62269ce434fSBarry Smith .  nleaves - number of leaf vertices on the current process, each of these references a root on any process
62369ce434fSBarry Smith .  ilocal - locations of leaves in leafdata buffers, pass NULL for contiguous storage
624cf79137fSStefano Zampini .  localmode - copy mode for ilocal
62569ce434fSBarry Smith -  iremote - remote locations of root vertices for each leaf on the current process
62669ce434fSBarry Smith 
62769ce434fSBarry Smith    Level: intermediate
62869ce434fSBarry Smith 
629cf79137fSStefano Zampini    Developers Note: Local indices which are the identity permutation in the range [0,nleaves) are discarded as they
630cf79137fSStefano Zampini    encode contiguous storage. In such case, if localmode is PETSC_OWN_POINTER, the memory is deallocated as it is not
631cf79137fSStefano Zampini    needed
632cf79137fSStefano Zampini 
63369ce434fSBarry Smith .seealso: PetscSFCreate(), PetscSFView(), PetscSFSetGraph(), PetscSFGetGraph()
63469ce434fSBarry Smith @*/
63569ce434fSBarry Smith PetscErrorCode PetscSFSetGraphLayout(PetscSF sf,PetscLayout layout,PetscInt nleaves,const PetscInt *ilocal,PetscCopyMode localmode,const PetscInt *iremote)
63669ce434fSBarry Smith {
63769ce434fSBarry Smith   PetscErrorCode ierr;
63869ce434fSBarry Smith   PetscInt       i,nroots;
63969ce434fSBarry Smith   PetscSFNode    *remote;
64069ce434fSBarry Smith 
64169ce434fSBarry Smith   PetscFunctionBegin;
64269ce434fSBarry Smith   ierr = PetscLayoutGetLocalSize(layout,&nroots);CHKERRQ(ierr);
643785e854fSJed Brown   ierr = PetscMalloc1(nleaves,&remote);CHKERRQ(ierr);
64469ce434fSBarry Smith   for (i=0; i<nleaves; i++) {
645131c27b5Sprj-     PetscMPIInt owner = -1;
64669ce434fSBarry Smith     ierr = PetscLayoutFindOwner(layout,iremote[i],&owner);CHKERRQ(ierr);
64769ce434fSBarry Smith     remote[i].rank  = owner;
64869ce434fSBarry Smith     remote[i].index = iremote[i] - layout->range[owner];
64969ce434fSBarry Smith   }
65069ce434fSBarry Smith   ierr = PetscSFSetGraph(sf,nroots,nleaves,ilocal,localmode,remote,PETSC_OWN_POINTER);CHKERRQ(ierr);
65169ce434fSBarry Smith   PetscFunctionReturn(0);
65269ce434fSBarry Smith }
65369ce434fSBarry Smith 
654f92d6284SStefano Zampini /*@
655f92d6284SStefano Zampini   PetscLayoutCompare - Compares two layouts
656f92d6284SStefano Zampini 
657f92d6284SStefano Zampini   Not Collective
658f92d6284SStefano Zampini 
659f92d6284SStefano Zampini   Input Parameters:
660d11c674dSStefano Zampini + mapa - pointer to the first map
661f92d6284SStefano Zampini - mapb - pointer to the second map
662f92d6284SStefano Zampini 
663f92d6284SStefano Zampini   Output Parameters:
664f92d6284SStefano Zampini . congruent - PETSC_TRUE if the two layouts are congruent, PETSC_FALSE otherwise
665f92d6284SStefano Zampini 
666f92d6284SStefano Zampini   Level: beginner
667f92d6284SStefano Zampini 
668f92d6284SStefano Zampini   Notes:
669f92d6284SStefano Zampini 
670f92d6284SStefano Zampini .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
671f92d6284SStefano Zampini           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
672f92d6284SStefano Zampini @*/
673f92d6284SStefano Zampini PetscErrorCode PetscLayoutCompare(PetscLayout mapa,PetscLayout mapb,PetscBool *congruent)
674f92d6284SStefano Zampini {
675f92d6284SStefano Zampini   PetscErrorCode ierr;
676f92d6284SStefano Zampini   PetscMPIInt    sizea,sizeb;
677f92d6284SStefano Zampini 
678f92d6284SStefano Zampini   PetscFunctionBegin;
679f92d6284SStefano Zampini   *congruent = PETSC_FALSE;
680f92d6284SStefano Zampini   ierr = MPI_Comm_size(mapa->comm,&sizea);CHKERRQ(ierr);
681f92d6284SStefano Zampini   ierr = MPI_Comm_size(mapb->comm,&sizeb);CHKERRQ(ierr);
682f92d6284SStefano Zampini   if (mapa->N == mapb->N && mapa->range && mapb->range && sizea == sizeb) {
683580bdb30SBarry Smith     ierr = PetscArraycmp(mapa->range,mapb->range,sizea+1,congruent);CHKERRQ(ierr);
684f92d6284SStefano Zampini   }
685f92d6284SStefano Zampini   PetscFunctionReturn(0);
686f92d6284SStefano Zampini }
687a72d46e8SStefano Zampini 
688a72d46e8SStefano Zampini /* TODO: handle nooffprocentries like MatZeroRowsMapLocal_Private, since this code is the same */
689a72d46e8SStefano Zampini PetscErrorCode PetscLayoutMapLocal(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
690a72d46e8SStefano Zampini {
691a72d46e8SStefano Zampini   PetscInt      *owners = map->range;
692a72d46e8SStefano Zampini   PetscInt       n      = map->n;
693a72d46e8SStefano Zampini   PetscSF        sf;
694a72d46e8SStefano Zampini   PetscInt      *lidxs,*work = NULL;
695a72d46e8SStefano Zampini   PetscSFNode   *ridxs;
696131c27b5Sprj-   PetscMPIInt    rank, p = 0;
697131c27b5Sprj-   PetscInt       r, len = 0;
698a72d46e8SStefano Zampini   PetscErrorCode ierr;
699a72d46e8SStefano Zampini 
700a72d46e8SStefano Zampini   PetscFunctionBegin;
701a72d46e8SStefano Zampini   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
702a72d46e8SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs */
703a72d46e8SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
704a72d46e8SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
705a72d46e8SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
706a72d46e8SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
707a72d46e8SStefano Zampini   for (r = 0; r < N; ++r) {
708a72d46e8SStefano Zampini     const PetscInt idx = idxs[r];
709a72d46e8SStefano 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);
710a72d46e8SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
711a72d46e8SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
712a72d46e8SStefano Zampini     }
713a72d46e8SStefano Zampini     ridxs[r].rank = p;
714a72d46e8SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
715a72d46e8SStefano Zampini   }
716a72d46e8SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
717a72d46e8SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
718a72d46e8SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
719a72d46e8SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
720a72d46e8SStefano Zampini   if (ogidxs) { /* communicate global idxs */
721a72d46e8SStefano Zampini     PetscInt cum = 0,start,*work2;
722a72d46e8SStefano Zampini 
723a72d46e8SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
724a72d46e8SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
725a72d46e8SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
726a72d46e8SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
727a72d46e8SStefano Zampini     start -= cum;
728a72d46e8SStefano Zampini     cum = 0;
729a72d46e8SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
730a72d46e8SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
731a72d46e8SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
732a72d46e8SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
733a72d46e8SStefano Zampini   }
734a72d46e8SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
735a72d46e8SStefano Zampini   /* Compress and put in indices */
736a72d46e8SStefano Zampini   for (r = 0; r < n; ++r)
737a72d46e8SStefano Zampini     if (lidxs[r] >= 0) {
738a72d46e8SStefano Zampini       if (work) work[len] = work[r];
739a72d46e8SStefano Zampini       lidxs[len++] = r;
740a72d46e8SStefano Zampini     }
741a72d46e8SStefano Zampini   if (on) *on = len;
742a72d46e8SStefano Zampini   if (oidxs) *oidxs = lidxs;
743a72d46e8SStefano Zampini   if (ogidxs) *ogidxs = work;
744a72d46e8SStefano Zampini   PetscFunctionReturn(0);
745a72d46e8SStefano Zampini }
746