xref: /petsc/src/vec/is/utils/pmap.c (revision e1b2f2751f01d80738f1da80a0d2be509cd15596)
169ce434fSBarry Smith /*
269ce434fSBarry Smith    This file contains routines for basic map object implementation.
369ce434fSBarry Smith */
469ce434fSBarry Smith 
557e2745dSVaclav Hapla #include <petsc/private/isimpl.h> /*I "petscis.h" I*/
65c25fcd7SBarry Smith 
7c3002683SMatthew G. Knepley /*@
8cab54364SBarry Smith   PetscLayoutCreate - Allocates `PetscLayout` object
969ce434fSBarry Smith 
10d083f849SBarry Smith   Collective
1169ce434fSBarry Smith 
122fe279fdSBarry Smith   Input Parameter:
13a8643c1eSVaclav Hapla . comm - the MPI communicator
14a8643c1eSVaclav Hapla 
152fe279fdSBarry Smith   Output Parameter:
16cab54364SBarry Smith . map - the new `PetscLayout`
1769ce434fSBarry Smith 
18456fcb79SJed Brown   Level: advanced
1969ce434fSBarry Smith 
20456fcb79SJed Brown   Notes:
21456fcb79SJed Brown   Typical calling sequence
22456fcb79SJed Brown .vb
2369ce434fSBarry Smith        PetscLayoutCreate(MPI_Comm,PetscLayout *);
24a8643c1eSVaclav Hapla        PetscLayoutSetBlockSize(PetscLayout,bs);
25a8643c1eSVaclav Hapla        PetscLayoutSetSize(PetscLayout,N); // or PetscLayoutSetLocalSize(PetscLayout,n);
2669ce434fSBarry Smith        PetscLayoutSetUp(PetscLayout);
27456fcb79SJed Brown .ve
289621ec18SVaclav Hapla   Alternatively,
29147403d9SBarry Smith .vb
30147403d9SBarry Smith       PetscLayoutCreateFromSizes(comm,n,N,bs,&layout);
31147403d9SBarry Smith .ve
329621ec18SVaclav Hapla 
33147403d9SBarry Smith   Optionally use any of the following
34147403d9SBarry Smith .vb
35147403d9SBarry Smith   PetscLayoutGetSize(PetscLayout,PetscInt *);
36147403d9SBarry Smith   PetscLayoutGetLocalSize(PetscLayout,PetscInt *);
37147403d9SBarry Smith   PetscLayoutGetRange(PetscLayout,PetscInt *rstart,PetscInt *rend);
38147403d9SBarry Smith   PetscLayoutGetRanges(PetscLayout,const PetscInt *range[]);
39147403d9SBarry Smith   PetscLayoutDestroy(PetscLayout*);
40147403d9SBarry Smith .ve
4169ce434fSBarry Smith 
42cab54364SBarry Smith   The `PetscLayout` object and methods are intended to be used in the PETSc `Vec` and `Mat` implementations; it is often not needed in
4369ce434fSBarry Smith   user codes unless you really gain something in their use.
4469ce434fSBarry Smith 
45cab54364SBarry Smith .seealso: [PetscLayout](sec_matlayout), `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`,
46cab54364SBarry Smith           `PetscLayout`, `PetscLayoutDestroy()`,
47db781477SPatrick Sanan           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`,
48db781477SPatrick Sanan           `PetscLayoutCreateFromSizes()`
4969ce434fSBarry Smith @*/
50d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLayoutCreate(MPI_Comm comm, PetscLayout *map)
51d71ae5a4SJacob Faibussowitsch {
5269ce434fSBarry Smith   PetscFunctionBegin;
539566063dSJacob Faibussowitsch   PetscCall(PetscNew(map));
549566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &(*map)->size));
5569ce434fSBarry Smith   (*map)->comm        = comm;
5658b7e2c1SStefano Zampini   (*map)->bs          = 1;
5769ce434fSBarry Smith   (*map)->n           = -1;
5869ce434fSBarry Smith   (*map)->N           = -1;
59f92d6284SStefano Zampini   (*map)->range       = NULL;
609621ec18SVaclav Hapla   (*map)->range_alloc = PETSC_TRUE;
6169ce434fSBarry Smith   (*map)->rstart      = 0;
6269ce434fSBarry Smith   (*map)->rend        = 0;
63ca5434daSLawrence Mitchell   (*map)->setupcalled = PETSC_FALSE;
64ca5434daSLawrence Mitchell   (*map)->oldn        = -1;
65ca5434daSLawrence Mitchell   (*map)->oldN        = -1;
66ca5434daSLawrence Mitchell   (*map)->oldbs       = -1;
673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6869ce434fSBarry Smith }
6969ce434fSBarry Smith 
70c3002683SMatthew G. Knepley /*@
71cab54364SBarry Smith   PetscLayoutCreateFromSizes - Allocates `PetscLayout` object and sets the layout sizes, and sets the layout up.
729621ec18SVaclav Hapla 
739621ec18SVaclav Hapla   Collective
749621ec18SVaclav Hapla 
759621ec18SVaclav Hapla   Input Parameters:
769621ec18SVaclav Hapla + comm - the MPI communicator
77cab54364SBarry Smith . n    - the local size (or `PETSC_DECIDE`)
78cab54364SBarry Smith . N    - the global size (or `PETSC_DECIDE`)
79cab54364SBarry Smith - bs   - the block size (or `PETSC_DECIDE`)
809621ec18SVaclav Hapla 
812fe279fdSBarry Smith   Output Parameter:
82cab54364SBarry Smith . map - the new `PetscLayout`
839621ec18SVaclav Hapla 
849621ec18SVaclav Hapla   Level: advanced
859621ec18SVaclav Hapla 
86cab54364SBarry Smith   Note:
87b44f4de4SBarry Smith .vb
88b44f4de4SBarry Smith   PetscLayoutCreateFromSizes(comm, n, N, bs, &layout);
89b44f4de4SBarry Smith .ve
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 
99cab54364SBarry Smith .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`,
100db781477SPatrick Sanan           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`, `PetscLayoutCreateFromRanges()`
1019621ec18SVaclav Hapla @*/
102d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLayoutCreateFromSizes(MPI_Comm comm, PetscInt n, PetscInt N, PetscInt bs, PetscLayout *map)
103d71ae5a4SJacob Faibussowitsch {
1049621ec18SVaclav Hapla   PetscFunctionBegin;
1059566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, map));
1069566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(*map, n));
1079566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetSize(*map, N));
1089566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(*map, bs));
1099566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(*map));
1103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1119621ec18SVaclav Hapla }
1129621ec18SVaclav Hapla 
1139621ec18SVaclav Hapla /*@
114cab54364SBarry Smith   PetscLayoutDestroy - Frees a `PetscLayout` object and frees its range if that exists.
11569ce434fSBarry Smith 
116d083f849SBarry Smith   Collective
11769ce434fSBarry Smith 
1182fe279fdSBarry Smith   Input Parameter:
119cab54364SBarry Smith . map - the `PetscLayout`
12069ce434fSBarry Smith 
12169ce434fSBarry Smith   Level: developer
12269ce434fSBarry Smith 
123cab54364SBarry Smith .seealso: [PetscLayout](sec_matlayout), `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`,
124cab54364SBarry Smith           `PetscLayout`, `PetscLayoutCreate()`,
125db781477SPatrick Sanan           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`
12669ce434fSBarry Smith @*/
127d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLayoutDestroy(PetscLayout *map)
128d71ae5a4SJacob Faibussowitsch {
12969ce434fSBarry Smith   PetscFunctionBegin;
1303ba16761SJacob Faibussowitsch   if (!*map) PetscFunctionReturn(PETSC_SUCCESS);
13169ce434fSBarry Smith   if (!(*map)->refcnt--) {
1329566063dSJacob Faibussowitsch     if ((*map)->range_alloc) PetscCall(PetscFree((*map)->range));
1339566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&(*map)->mapping));
134f4f49eeaSPierre Jolivet     PetscCall(PetscFree(*map));
13569ce434fSBarry Smith   }
13669ce434fSBarry Smith   *map = NULL;
1373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13869ce434fSBarry Smith }
13969ce434fSBarry Smith 
1409621ec18SVaclav Hapla /*@
141cab54364SBarry Smith   PetscLayoutCreateFromRanges - Creates a new `PetscLayout` with the given ownership ranges and sets it up.
1429621ec18SVaclav Hapla 
1439621ec18SVaclav Hapla   Collective
1449621ec18SVaclav Hapla 
1459621ec18SVaclav Hapla   Input Parameters:
1469621ec18SVaclav Hapla + comm  - the MPI communicator
1479621ec18SVaclav Hapla . range - the array of ownership ranges for each rank with length commsize+1
1489621ec18SVaclav Hapla . mode  - the copy mode for range
149cab54364SBarry Smith - bs    - the block size (or `PETSC_DECIDE`)
1509621ec18SVaclav Hapla 
1512fe279fdSBarry Smith   Output Parameter:
152cab54364SBarry Smith . newmap - the new `PetscLayout`
1539621ec18SVaclav Hapla 
1549621ec18SVaclav Hapla   Level: developer
1559621ec18SVaclav Hapla 
156cab54364SBarry Smith .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`,
157cab54364SBarry Smith           `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`,
158db781477SPatrick Sanan           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`, `PetscLayoutCreateFromSizes()`
1599621ec18SVaclav Hapla @*/
160d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLayoutCreateFromRanges(MPI_Comm comm, const PetscInt range[], PetscCopyMode mode, PetscInt bs, PetscLayout *newmap)
161d71ae5a4SJacob Faibussowitsch {
1629621ec18SVaclav Hapla   PetscLayout map;
16338a25198SStefano Zampini   PetscMPIInt rank;
1647b659617SVaclav Hapla 
1657b659617SVaclav Hapla   PetscFunctionBegin;
1669566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1679566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &map));
1689566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(map, bs));
1699621ec18SVaclav Hapla   switch (mode) {
1709621ec18SVaclav Hapla   case PETSC_COPY_VALUES:
1719566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(map->size + 1, &map->range));
1729566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(map->range, range, map->size + 1));
1739621ec18SVaclav Hapla     break;
174d71ae5a4SJacob Faibussowitsch   case PETSC_USE_POINTER:
175d71ae5a4SJacob Faibussowitsch     map->range_alloc = PETSC_FALSE;
176d71ae5a4SJacob Faibussowitsch     break;
177d71ae5a4SJacob Faibussowitsch   default:
178d71ae5a4SJacob Faibussowitsch     map->range = (PetscInt *)range;
179d71ae5a4SJacob Faibussowitsch     break;
1809621ec18SVaclav Hapla   }
1817b659617SVaclav Hapla   map->rstart = map->range[rank];
1827b659617SVaclav Hapla   map->rend   = map->range[rank + 1];
1837b659617SVaclav Hapla   map->n      = map->rend - map->rstart;
18438a25198SStefano Zampini   map->N      = map->range[map->size];
18576bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) { /* just check that n, N and bs are consistent */
1867b659617SVaclav Hapla     PetscInt tmp;
187462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(&map->n, &tmp, 1, MPIU_INT, MPI_SUM, map->comm));
18800045ab3SPierre Jolivet     PetscCheck(tmp == map->N, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Sum of local lengths %" PetscInt_FMT " does not equal global length %" PetscInt_FMT ", my local length %" PetscInt_FMT ". The provided PetscLayout is wrong.", tmp, map->N, map->n);
18958b7e2c1SStefano Zampini     PetscCheck(map->n % map->bs == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local size %" PetscInt_FMT " must be divisible by blocksize %" PetscInt_FMT, map->n, map->bs);
19058b7e2c1SStefano Zampini     PetscCheck(map->N % map->bs == 0, map->comm, PETSC_ERR_PLIB, "Global size %" PetscInt_FMT " must be divisible by blocksize %" PetscInt_FMT, map->N, map->bs);
19176bd3646SJed Brown   }
192ca5434daSLawrence Mitchell   /* lock the layout */
193ca5434daSLawrence Mitchell   map->setupcalled = PETSC_TRUE;
194ca5434daSLawrence Mitchell   map->oldn        = map->n;
195ca5434daSLawrence Mitchell   map->oldN        = map->N;
196ca5434daSLawrence Mitchell   map->oldbs       = map->bs;
1979621ec18SVaclav Hapla   *newmap          = map;
1983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1997b659617SVaclav Hapla }
2007b659617SVaclav Hapla 
201c3002683SMatthew G. Knepley /*@
20269ce434fSBarry Smith   PetscLayoutSetUp - given a map where you have set either the global or local
20369ce434fSBarry Smith   size sets up the map so that it may be used.
20469ce434fSBarry Smith 
205d083f849SBarry Smith   Collective
20669ce434fSBarry Smith 
2072fe279fdSBarry Smith   Input Parameter:
20869ce434fSBarry Smith . map - pointer to the map
20969ce434fSBarry Smith 
21069ce434fSBarry Smith   Level: developer
21169ce434fSBarry Smith 
21295452b02SPatrick Sanan   Notes:
21395452b02SPatrick Sanan   Typical calling sequence
214cab54364SBarry Smith .vb
215cab54364SBarry Smith   PetscLayoutCreate(MPI_Comm,PetscLayout *);
216cab54364SBarry Smith   PetscLayoutSetBlockSize(PetscLayout,1);
217cab54364SBarry Smith   PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both
218cab54364SBarry Smith   PetscLayoutSetUp(PetscLayout);
219cab54364SBarry Smith   PetscLayoutGetSize(PetscLayout,PetscInt *);
220cab54364SBarry Smith .ve
22169ce434fSBarry Smith 
2227b659617SVaclav Hapla   If range exists, and local size is not set, everything gets computed from the range.
22369ce434fSBarry Smith 
22469ce434fSBarry Smith   If the local size, global size are already set and range exists then this does nothing.
22569ce434fSBarry Smith 
226cab54364SBarry Smith .seealso: [PetscLayout](sec_matlayout), `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`,
227cab54364SBarry Smith           `PetscLayout`, `PetscLayoutDestroy()`,
228f1f2ae84SBarry Smith           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutCreate()`, `PetscSplitOwnership()`
22969ce434fSBarry Smith @*/
230d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLayoutSetUp(PetscLayout map)
231d71ae5a4SJacob Faibussowitsch {
23238a25198SStefano Zampini   PetscMPIInt rank;
23369ce434fSBarry Smith   PetscInt    p;
23469ce434fSBarry Smith 
23569ce434fSBarry Smith   PetscFunctionBegin;
2369371c9d4SSatish Balay   PetscCheck(!map->setupcalled || !(map->n != map->oldn || map->N != map->oldN), map->comm, PETSC_ERR_ARG_WRONGSTATE, "Layout is already setup with (local=%" PetscInt_FMT ",global=%" PetscInt_FMT "), cannot call setup again with (local=%" PetscInt_FMT ",global=%" PetscInt_FMT ")",
2379371c9d4SSatish Balay              map->oldn, map->oldN, map->n, map->N);
2383ba16761SJacob Faibussowitsch   if (map->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
23969ce434fSBarry Smith 
24058b7e2c1SStefano Zampini   PetscCheck(map->n < 0 || map->n % map->bs == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local size %" PetscInt_FMT " must be divisible by blocksize %" PetscInt_FMT, map->n, map->bs);
24158b7e2c1SStefano Zampini   PetscCheck(map->N < 0 || map->N % map->bs == 0, map->comm, PETSC_ERR_PLIB, "Global size %" PetscInt_FMT " must be divisible by blocksize %" PetscInt_FMT, map->N, map->bs);
242b146b01cSBarry Smith 
2439566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(map->comm, &rank));
24458b7e2c1SStefano Zampini   if (map->n > 0) map->n = map->n / map->bs;
24558b7e2c1SStefano Zampini   if (map->N > 0) map->N = map->N / map->bs;
2469566063dSJacob Faibussowitsch   PetscCall(PetscSplitOwnership(map->comm, &map->n, &map->N));
24758b7e2c1SStefano Zampini   map->n = map->n * map->bs;
24858b7e2c1SStefano Zampini   map->N = map->N * map->bs;
24948a46eb9SPierre Jolivet   if (!map->range) PetscCall(PetscMalloc1(map->size + 1, &map->range));
2509566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allgather(&map->n, 1, MPIU_INT, map->range + 1, 1, MPIU_INT, map->comm));
25169ce434fSBarry Smith 
25269ce434fSBarry Smith   map->range[0] = 0;
25338a25198SStefano Zampini   for (p = 2; p <= map->size; p++) map->range[p] += map->range[p - 1];
25469ce434fSBarry Smith 
25569ce434fSBarry Smith   map->rstart = map->range[rank];
25669ce434fSBarry Smith   map->rend   = map->range[rank + 1];
257ca5434daSLawrence Mitchell 
258ca5434daSLawrence Mitchell   /* lock the layout */
259ca5434daSLawrence Mitchell   map->setupcalled = PETSC_TRUE;
260ca5434daSLawrence Mitchell   map->oldn        = map->n;
261ca5434daSLawrence Mitchell   map->oldN        = map->N;
262ca5434daSLawrence Mitchell   map->oldbs       = map->bs;
2633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26469ce434fSBarry Smith }
26569ce434fSBarry Smith 
266c3002683SMatthew G. Knepley /*@
267cab54364SBarry Smith   PetscLayoutDuplicate - creates a new `PetscLayout` with the same information as a given one. If the `PetscLayout` already exists it is destroyed first.
26869ce434fSBarry Smith 
269c3339decSBarry Smith   Collective
27069ce434fSBarry Smith 
27169ce434fSBarry Smith   Input Parameter:
272cab54364SBarry Smith . in - input `PetscLayout` to be duplicated
27369ce434fSBarry Smith 
27469ce434fSBarry Smith   Output Parameter:
27569ce434fSBarry Smith . out - the copy
27669ce434fSBarry Smith 
27769ce434fSBarry Smith   Level: developer
27869ce434fSBarry Smith 
279cab54364SBarry Smith   Note:
280cab54364SBarry Smith   `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout`
28169ce434fSBarry Smith 
282cab54364SBarry Smith .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutReference()`
28369ce434fSBarry Smith @*/
284d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLayoutDuplicate(PetscLayout in, PetscLayout *out)
285d71ae5a4SJacob Faibussowitsch {
28669ce434fSBarry Smith   MPI_Comm comm = in->comm;
28769ce434fSBarry Smith 
28869ce434fSBarry Smith   PetscFunctionBegin;
2899566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(out));
2909566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, out));
2919566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(*out, in, sizeof(struct _n_PetscLayout)));
292c168f6d8SVaclav Hapla   if (in->range) {
2939566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1((*out)->size + 1, &(*out)->range));
2949566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy((*out)->range, in->range, (*out)->size + 1));
295c168f6d8SVaclav Hapla   }
29669ce434fSBarry Smith   (*out)->refcnt = 0;
2973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29869ce434fSBarry Smith }
29969ce434fSBarry Smith 
300c3002683SMatthew G. Knepley /*@
301cab54364SBarry Smith   PetscLayoutReference - Causes a PETSc `Vec` or `Mat` to share a `PetscLayout` with one that already exists.
30269ce434fSBarry Smith 
303c3339decSBarry Smith   Collective
30469ce434fSBarry Smith 
30569ce434fSBarry Smith   Input Parameter:
306cab54364SBarry Smith . in - input `PetscLayout` to be copied
30769ce434fSBarry Smith 
30869ce434fSBarry Smith   Output Parameter:
30969ce434fSBarry Smith . out - the reference location
31069ce434fSBarry Smith 
31169ce434fSBarry Smith   Level: developer
31269ce434fSBarry Smith 
31395452b02SPatrick Sanan   Notes:
314cab54364SBarry Smith   `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout`
31569ce434fSBarry Smith 
316cab54364SBarry Smith   If the out location already contains a `PetscLayout` it is destroyed
31769ce434fSBarry Smith 
318cab54364SBarry Smith .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutDuplicate()`
31969ce434fSBarry Smith @*/
320d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLayoutReference(PetscLayout in, PetscLayout *out)
321d71ae5a4SJacob Faibussowitsch {
32269ce434fSBarry Smith   PetscFunctionBegin;
32369ce434fSBarry Smith   in->refcnt++;
3249566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(out));
32569ce434fSBarry Smith   *out = in;
3263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32769ce434fSBarry Smith }
32869ce434fSBarry Smith 
329c3002683SMatthew G. Knepley /*@
330cab54364SBarry Smith   PetscLayoutSetISLocalToGlobalMapping - sets a `ISLocalGlobalMapping` into a `PetscLayout`
33169ce434fSBarry Smith 
332c3339decSBarry Smith   Collective
33369ce434fSBarry Smith 
334d8d19677SJose E. Roman   Input Parameters:
335cab54364SBarry Smith + in   - input `PetscLayout`
33669ce434fSBarry Smith - ltog - the local to global mapping
33769ce434fSBarry Smith 
33869ce434fSBarry Smith   Level: developer
33969ce434fSBarry Smith 
34095452b02SPatrick Sanan   Notes:
341cab54364SBarry Smith   `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout`
34269ce434fSBarry Smith 
343cab54364SBarry Smith   If the `PetscLayout` already contains a `ISLocalGlobalMapping` it is destroyed
34469ce434fSBarry Smith 
345cab54364SBarry Smith .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutDuplicate()`
34669ce434fSBarry Smith @*/
347d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in, ISLocalToGlobalMapping ltog)
348d71ae5a4SJacob Faibussowitsch {
34969ce434fSBarry Smith   PetscFunctionBegin;
350fc989267SStefano Zampini   if (ltog) {
351fc989267SStefano Zampini     PetscInt bs;
352fc989267SStefano Zampini 
3539566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockSize(ltog, &bs));
35458b7e2c1SStefano Zampini     PetscCheck(in->bs == 1 || bs == 1 || in->bs == bs, in->comm, PETSC_ERR_PLIB, "Blocksize of layout %" PetscInt_FMT " must match that of mapping %" PetscInt_FMT " (or the latter must be 1)", in->bs, bs);
355fc989267SStefano Zampini   }
356da0802e2SStefano Zampini   PetscCall(PetscObjectReference((PetscObject)ltog));
3579566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&in->mapping));
35869ce434fSBarry Smith   in->mapping = ltog;
3593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
36069ce434fSBarry Smith }
36169ce434fSBarry Smith 
362c3002683SMatthew G. Knepley /*@
363cab54364SBarry Smith   PetscLayoutSetLocalSize - Sets the local size for a `PetscLayout` object.
36469ce434fSBarry Smith 
365c3339decSBarry Smith   Collective
36669ce434fSBarry Smith 
36769ce434fSBarry Smith   Input Parameters:
36869ce434fSBarry Smith + map - pointer to the map
369*e1b2f275SBarry Smith - n   - the local size, pass `PETSC_DECIDE` (the default) to have this value determined by the global size set with `PetscLayoutSetSize()`
37069ce434fSBarry Smith 
37169ce434fSBarry Smith   Level: developer
37269ce434fSBarry Smith 
373cab54364SBarry Smith .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetUp()`
374db781477SPatrick Sanan           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
37569ce434fSBarry Smith @*/
376d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map, PetscInt n)
377d71ae5a4SJacob Faibussowitsch {
37869ce434fSBarry Smith   PetscFunctionBegin;
37958b7e2c1SStefano Zampini   PetscCheck(n % map->bs == 0, map->comm, PETSC_ERR_ARG_INCOMP, "Local size %" PetscInt_FMT " not compatible with block size %" PetscInt_FMT, n, map->bs);
38069ce434fSBarry Smith   map->n = n;
3813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38269ce434fSBarry Smith }
38369ce434fSBarry Smith 
3844ffacfe2SAlexis Marboeuf /*@
385cab54364SBarry Smith   PetscLayoutGetLocalSize - Gets the local size for a `PetscLayout` object.
38669ce434fSBarry Smith 
38769ce434fSBarry Smith   Not Collective
38869ce434fSBarry Smith 
3892fe279fdSBarry Smith   Input Parameter:
39069ce434fSBarry Smith . map - pointer to the map
39169ce434fSBarry Smith 
3922fe279fdSBarry Smith   Output Parameter:
39369ce434fSBarry Smith . n - the local size
39469ce434fSBarry Smith 
39569ce434fSBarry Smith   Level: developer
39669ce434fSBarry Smith 
397cab54364SBarry Smith   Note:
398cab54364SBarry Smith   Call this after the call to `PetscLayoutSetUp()`
39969ce434fSBarry Smith 
40042747ad1SJacob Faibussowitsch .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
401db781477SPatrick Sanan           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
40269ce434fSBarry Smith @*/
403d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLayoutGetLocalSize(PetscLayout map, PetscInt *n)
404d71ae5a4SJacob Faibussowitsch {
40569ce434fSBarry Smith   PetscFunctionBegin;
40669ce434fSBarry Smith   *n = map->n;
4073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40869ce434fSBarry Smith }
40969ce434fSBarry Smith 
410c3002683SMatthew G. Knepley /*@
411cab54364SBarry Smith   PetscLayoutSetSize - Sets the global size for a `PetscLayout` object.
41269ce434fSBarry Smith 
413c3339decSBarry Smith   Logically Collective
41469ce434fSBarry Smith 
41569ce434fSBarry Smith   Input Parameters:
41669ce434fSBarry Smith + map - pointer to the map
417*e1b2f275SBarry Smith - n   - the global size, use `PETSC_DETERMINE` (the default) to have this value computed as the sum of the local sizes set with `PetscLayoutSetLocalSize()`
41869ce434fSBarry Smith 
41969ce434fSBarry Smith   Level: developer
42069ce434fSBarry Smith 
421cab54364SBarry Smith .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
422db781477SPatrick Sanan           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
42369ce434fSBarry Smith @*/
424d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLayoutSetSize(PetscLayout map, PetscInt n)
425d71ae5a4SJacob Faibussowitsch {
42669ce434fSBarry Smith   PetscFunctionBegin;
42769ce434fSBarry Smith   map->N = n;
4283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42969ce434fSBarry Smith }
43069ce434fSBarry Smith 
431c3002683SMatthew G. Knepley /*@
432cab54364SBarry Smith   PetscLayoutGetSize - Gets the global size for a `PetscLayout` object.
43369ce434fSBarry Smith 
43469ce434fSBarry Smith   Not Collective
43569ce434fSBarry Smith 
4362fe279fdSBarry Smith   Input Parameter:
43769ce434fSBarry Smith . map - pointer to the map
43869ce434fSBarry Smith 
4392fe279fdSBarry Smith   Output Parameter:
44069ce434fSBarry Smith . n - the global size
44169ce434fSBarry Smith 
44269ce434fSBarry Smith   Level: developer
44369ce434fSBarry Smith 
444cab54364SBarry Smith   Note:
445cab54364SBarry Smith   Call this after the call to `PetscLayoutSetUp()`
44669ce434fSBarry Smith 
447cab54364SBarry Smith .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutSetUp()`
448db781477SPatrick Sanan           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
44969ce434fSBarry Smith @*/
450d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLayoutGetSize(PetscLayout map, PetscInt *n)
451d71ae5a4SJacob Faibussowitsch {
45269ce434fSBarry Smith   PetscFunctionBegin;
45369ce434fSBarry Smith   *n = map->N;
4543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45569ce434fSBarry Smith }
45669ce434fSBarry Smith 
457c3002683SMatthew G. Knepley /*@
458cab54364SBarry Smith   PetscLayoutSetBlockSize - Sets the block size for a `PetscLayout` object.
45969ce434fSBarry Smith 
460c3339decSBarry Smith   Logically Collective
46169ce434fSBarry Smith 
46269ce434fSBarry Smith   Input Parameters:
46369ce434fSBarry Smith + map - pointer to the map
46469ce434fSBarry Smith - bs  - the size
46569ce434fSBarry Smith 
46669ce434fSBarry Smith   Level: developer
46769ce434fSBarry Smith 
468cab54364SBarry Smith .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetBlockSize()`,
469db781477SPatrick Sanan           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
47069ce434fSBarry Smith @*/
471d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map, PetscInt bs)
472d71ae5a4SJacob Faibussowitsch {
47369ce434fSBarry Smith   PetscFunctionBegin;
47458b7e2c1SStefano Zampini   PetscCheck(bs > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Block size %" PetscInt_FMT " must be positive", bs);
475c9cc58a2SBarry Smith   PetscCheck(map->n <= 0 || (map->n % bs) == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Local size %" PetscInt_FMT " not compatible with block size %" PetscInt_FMT, map->n, bs);
476565245c5SBarry Smith   if (map->mapping) {
477705e6b8bSstefano_zampini     PetscInt obs;
478565245c5SBarry Smith 
4799566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockSize(map->mapping, &obs));
48048a46eb9SPierre Jolivet     if (obs > 1) PetscCall(ISLocalToGlobalMappingSetBlockSize(map->mapping, bs));
481705e6b8bSstefano_zampini   }
48269ce434fSBarry Smith   map->bs = bs;
4833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48469ce434fSBarry Smith }
48569ce434fSBarry Smith 
486c3002683SMatthew G. Knepley /*@
487cab54364SBarry Smith   PetscLayoutGetBlockSize - Gets the block size for a `PetscLayout` object.
48869ce434fSBarry Smith 
48969ce434fSBarry Smith   Not Collective
49069ce434fSBarry Smith 
4912fe279fdSBarry Smith   Input Parameter:
49269ce434fSBarry Smith . map - pointer to the map
49369ce434fSBarry Smith 
4942fe279fdSBarry Smith   Output Parameter:
49569ce434fSBarry Smith . bs - the size
49669ce434fSBarry Smith 
49769ce434fSBarry Smith   Level: developer
49869ce434fSBarry Smith 
49969ce434fSBarry Smith   Notes:
500cab54364SBarry Smith   Call this after the call to `PetscLayoutSetUp()`
50169ce434fSBarry Smith 
502cab54364SBarry Smith .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutSetUp()`
503db781477SPatrick Sanan           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetSize()`
50469ce434fSBarry Smith @*/
505d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map, PetscInt *bs)
506d71ae5a4SJacob Faibussowitsch {
50769ce434fSBarry Smith   PetscFunctionBegin;
50858b7e2c1SStefano Zampini   *bs = map->bs;
5093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51069ce434fSBarry Smith }
51169ce434fSBarry Smith 
512c3002683SMatthew G. Knepley /*@
51369ce434fSBarry Smith   PetscLayoutGetRange - gets the range of values owned by this process
51469ce434fSBarry Smith 
51569ce434fSBarry Smith   Not Collective
51669ce434fSBarry Smith 
517f899ff85SJose E. Roman   Input Parameter:
51869ce434fSBarry Smith . map - pointer to the map
51969ce434fSBarry Smith 
52069ce434fSBarry Smith   Output Parameters:
52169ce434fSBarry Smith + rstart - first index owned by this process
52269ce434fSBarry Smith - rend   - one more than the last index owned by this process
52369ce434fSBarry Smith 
52469ce434fSBarry Smith   Level: developer
52569ce434fSBarry Smith 
526cab54364SBarry Smith   Note:
527cab54364SBarry Smith   Call this after the call to `PetscLayoutSetUp()`
52869ce434fSBarry Smith 
529cab54364SBarry Smith .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`,
53038b5cf2dSJacob Faibussowitsch           `PetscLayoutGetSize()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutSetUp()`
53169ce434fSBarry Smith @*/
532d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLayoutGetRange(PetscLayout map, PetscInt *rstart, PetscInt *rend)
533d71ae5a4SJacob Faibussowitsch {
53469ce434fSBarry Smith   PetscFunctionBegin;
53569ce434fSBarry Smith   if (rstart) *rstart = map->rstart;
53669ce434fSBarry Smith   if (rend) *rend = map->rend;
5373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
53869ce434fSBarry Smith }
53969ce434fSBarry Smith 
54069ce434fSBarry Smith /*@C
541cab54364SBarry Smith   PetscLayoutGetRanges - gets the ranges of values owned by all processes
54269ce434fSBarry Smith 
54369ce434fSBarry Smith   Not Collective
54469ce434fSBarry Smith 
5452fe279fdSBarry Smith   Input Parameter:
54669ce434fSBarry Smith . map - pointer to the map
54769ce434fSBarry Smith 
5482fe279fdSBarry Smith   Output Parameter:
549c3b5f7baSPierre Jolivet . range - start of each processors range of indices (the final entry is one more than the
5502c9a7b26SBarry Smith           last index on the last process). The length of the array is one more than the number of processes in the MPI
5512c9a7b26SBarry Smith           communicator owned by `map`
55269ce434fSBarry Smith 
55369ce434fSBarry Smith   Level: developer
55469ce434fSBarry Smith 
555cab54364SBarry Smith   Note:
556cab54364SBarry Smith   Call this after the call to `PetscLayoutSetUp()`
55769ce434fSBarry Smith 
55838b5cf2dSJacob Faibussowitsch   Fortran Notes:
559ce78bad3SBarry Smith .vb
560ce78bad3SBarry Smith   PetscInt, pointer :: range(:)
561ce78bad3SBarry Smith .ve
562ce78bad3SBarry Smith 
563ce78bad3SBarry Smith   Call `PetscLayoutRestoreRanges()` when no longer needed.
56469ce434fSBarry Smith 
565cab54364SBarry Smith .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`,
56638b5cf2dSJacob Faibussowitsch           `PetscLayoutGetSize()`, `PetscLayoutGetRange()`, `PetscLayoutSetBlockSize()`, `PetscLayoutSetUp()`
56769ce434fSBarry Smith @*/
568d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLayoutGetRanges(PetscLayout map, const PetscInt *range[])
569d71ae5a4SJacob Faibussowitsch {
57069ce434fSBarry Smith   PetscFunctionBegin;
57169ce434fSBarry Smith   *range = map->range;
5723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57369ce434fSBarry Smith }
57469ce434fSBarry Smith 
575f92d6284SStefano Zampini /*@
576f92d6284SStefano Zampini   PetscLayoutCompare - Compares two layouts
577f92d6284SStefano Zampini 
578f92d6284SStefano Zampini   Not Collective
579f92d6284SStefano Zampini 
580f92d6284SStefano Zampini   Input Parameters:
581d11c674dSStefano Zampini + mapa - pointer to the first map
582f92d6284SStefano Zampini - mapb - pointer to the second map
583f92d6284SStefano Zampini 
5842fe279fdSBarry Smith   Output Parameter:
585cab54364SBarry Smith . congruent - `PETSC_TRUE` if the two layouts are congruent, `PETSC_FALSE` otherwise
586f92d6284SStefano Zampini 
587f92d6284SStefano Zampini   Level: beginner
588f92d6284SStefano Zampini 
589cab54364SBarry Smith .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetBlockSize()`,
590db781477SPatrick Sanan           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
591f92d6284SStefano Zampini @*/
592d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLayoutCompare(PetscLayout mapa, PetscLayout mapb, PetscBool *congruent)
593d71ae5a4SJacob Faibussowitsch {
594f92d6284SStefano Zampini   PetscFunctionBegin;
595f92d6284SStefano Zampini   *congruent = PETSC_FALSE;
59648a46eb9SPierre Jolivet   if (mapa->N == mapb->N && mapa->range && mapb->range && mapa->size == mapb->size) PetscCall(PetscArraycmp(mapa->range, mapb->range, mapa->size + 1, congruent));
5973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
598f92d6284SStefano Zampini }
5995d83a8b1SBarry Smith 
6005d83a8b1SBarry Smith /*@
6015d83a8b1SBarry Smith   PetscLayoutFindOwner - Find the owning MPI process for a global index
6025d83a8b1SBarry Smith 
6035d83a8b1SBarry Smith   Not Collective; No Fortran Support
6045d83a8b1SBarry Smith 
6055d83a8b1SBarry Smith   Input Parameters:
6065d83a8b1SBarry Smith + map - the layout
6075d83a8b1SBarry Smith - idx - global index to find the owner of
6085d83a8b1SBarry Smith 
6095d83a8b1SBarry Smith   Output Parameter:
6105d83a8b1SBarry Smith . owner - the owning rank
6115d83a8b1SBarry Smith 
6125d83a8b1SBarry Smith   Level: developer
6135d83a8b1SBarry Smith 
6145d83a8b1SBarry Smith .seealso: `PetscLayout`, `PetscLayoutFindOwnerIndex()`
6155d83a8b1SBarry Smith @*/
6165d83a8b1SBarry Smith PetscErrorCode PetscLayoutFindOwner(PetscLayout map, PetscInt idx, PetscMPIInt *owner)
6175d83a8b1SBarry Smith {
6185d83a8b1SBarry Smith   PetscMPIInt lo = 0, hi, t;
6195d83a8b1SBarry Smith 
6205d83a8b1SBarry Smith   PetscFunctionBegin;
6215d83a8b1SBarry Smith   *owner = -1; /* GCC erroneously issues warning about possibly uninitialized use when error condition */
6225d83a8b1SBarry Smith   PetscAssert((map->n >= 0) && (map->N >= 0) && (map->range), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscLayoutSetUp() must be called first");
6235d83a8b1SBarry Smith   PetscAssert(idx >= 0 && idx <= map->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Index %" PetscInt_FMT " is out of range", idx);
6245d83a8b1SBarry Smith   hi = map->size;
6255d83a8b1SBarry Smith   while (hi - lo > 1) {
6265d83a8b1SBarry Smith     t = lo + (hi - lo) / 2;
6275d83a8b1SBarry Smith     if (idx < map->range[t]) hi = t;
6285d83a8b1SBarry Smith     else lo = t;
6295d83a8b1SBarry Smith   }
6305d83a8b1SBarry Smith   *owner = lo;
6315d83a8b1SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
6325d83a8b1SBarry Smith }
6335d83a8b1SBarry Smith 
6345d83a8b1SBarry Smith /*@
6355d83a8b1SBarry Smith   PetscLayoutFindOwnerIndex - Find the owning MPI process and the local index on that process for a global index
6365d83a8b1SBarry Smith 
6375d83a8b1SBarry Smith   Not Collective; No Fortran Support
6385d83a8b1SBarry Smith 
6395d83a8b1SBarry Smith   Input Parameters:
6405d83a8b1SBarry Smith + map - the layout
6415d83a8b1SBarry Smith - idx - global index to find the owner of
6425d83a8b1SBarry Smith 
6435d83a8b1SBarry Smith   Output Parameters:
6445d83a8b1SBarry Smith + owner - the owning rank
6455d83a8b1SBarry Smith - lidx  - local index used by the owner for `idx`
6465d83a8b1SBarry Smith 
6475d83a8b1SBarry Smith   Level: developer
6485d83a8b1SBarry Smith 
6495d83a8b1SBarry Smith .seealso: `PetscLayout`, `PetscLayoutFindOwner()`
6505d83a8b1SBarry Smith @*/
6515d83a8b1SBarry Smith PetscErrorCode PetscLayoutFindOwnerIndex(PetscLayout map, PetscInt idx, PetscMPIInt *owner, PetscInt *lidx)
6525d83a8b1SBarry Smith {
6535d83a8b1SBarry Smith   PetscMPIInt lo = 0, hi, t;
6545d83a8b1SBarry Smith 
6555d83a8b1SBarry Smith   PetscFunctionBegin;
6565d83a8b1SBarry Smith   PetscAssert((map->n >= 0) && (map->N >= 0) && (map->range), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscLayoutSetUp() must be called first");
6575d83a8b1SBarry Smith   PetscAssert(idx >= 0 && idx <= map->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Index %" PetscInt_FMT " is out of range", idx);
6585d83a8b1SBarry Smith   hi = map->size;
6595d83a8b1SBarry Smith   while (hi - lo > 1) {
6605d83a8b1SBarry Smith     t = lo + (hi - lo) / 2;
6615d83a8b1SBarry Smith     if (idx < map->range[t]) hi = t;
6625d83a8b1SBarry Smith     else lo = t;
6635d83a8b1SBarry Smith   }
6645d83a8b1SBarry Smith   if (owner) *owner = lo;
6655d83a8b1SBarry Smith   if (lidx) *lidx = idx - map->range[lo];
6665d83a8b1SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
6675d83a8b1SBarry Smith }
668