xref: /petsc/src/vec/is/utils/pmap.c (revision f26271d2d7c4dd1ad5e4ef1066d481888558d6fe)
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)
81f0fc11ceSJed 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];
19576bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {  /* just check that n, N and bs are consistent */
1967b659617SVaclav Hapla     PetscInt tmp;
1977b659617SVaclav Hapla     ierr = MPIU_Allreduce(&map->n,&tmp,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
1987b659617SVaclav 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);
1997b659617SVaclav Hapla     if (map->bs > 1) {
2007b659617SVaclav 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);
2017b659617SVaclav Hapla     }
2027b659617SVaclav Hapla     if (map->bs > 1) {
2037b659617SVaclav 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);
2047b659617SVaclav Hapla     }
20576bd3646SJed Brown   }
206ca5434daSLawrence Mitchell   /* lock the layout */
207ca5434daSLawrence Mitchell   map->setupcalled = PETSC_TRUE;
208ca5434daSLawrence Mitchell   map->oldn = map->n;
209ca5434daSLawrence Mitchell   map->oldN = map->N;
210ca5434daSLawrence Mitchell   map->oldbs = map->bs;
2119621ec18SVaclav Hapla   *newmap = map;
2127b659617SVaclav Hapla   PetscFunctionReturn(0);
2137b659617SVaclav Hapla }
2147b659617SVaclav Hapla 
215c3002683SMatthew G. Knepley /*@
21669ce434fSBarry Smith   PetscLayoutSetUp - given a map where you have set either the global or local
21769ce434fSBarry Smith                      size sets up the map so that it may be used.
21869ce434fSBarry Smith 
219d083f849SBarry Smith   Collective
22069ce434fSBarry Smith 
22169ce434fSBarry Smith   Input Parameters:
22269ce434fSBarry Smith . map - pointer to the map
22369ce434fSBarry Smith 
22469ce434fSBarry Smith   Level: developer
22569ce434fSBarry Smith 
22695452b02SPatrick Sanan   Notes:
22795452b02SPatrick Sanan     Typical calling sequence
228c3002683SMatthew G. Knepley $ PetscLayoutCreate(MPI_Comm,PetscLayout *);
229c3002683SMatthew G. Knepley $ PetscLayoutSetBlockSize(PetscLayout,1);
230c3002683SMatthew G. Knepley $ PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both
231c3002683SMatthew G. Knepley $ PetscLayoutSetUp(PetscLayout);
232c3002683SMatthew G. Knepley $ PetscLayoutGetSize(PetscLayout,PetscInt *);
23369ce434fSBarry Smith 
2347b659617SVaclav Hapla   If range exists, and local size is not set, everything gets computed from the range.
23569ce434fSBarry Smith 
23669ce434fSBarry Smith   If the local size, global size are already set and range exists then this does nothing.
23769ce434fSBarry Smith 
23869ce434fSBarry Smith .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
23969ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutCreate()
24069ce434fSBarry Smith @*/
24169ce434fSBarry Smith PetscErrorCode PetscLayoutSetUp(PetscLayout map)
24269ce434fSBarry Smith {
24369ce434fSBarry Smith   PetscMPIInt    rank,size;
24469ce434fSBarry Smith   PetscInt       p;
24569ce434fSBarry Smith   PetscErrorCode ierr;
24669ce434fSBarry Smith 
24769ce434fSBarry Smith   PetscFunctionBegin;
248ca5434daSLawrence 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);
249ca5434daSLawrence Mitchell   if (map->setupcalled) PetscFunctionReturn(0);
25069ce434fSBarry Smith 
251b146b01cSBarry Smith   if (map->n > 0 && map->bs > 1) {
252ec4d677dSStefano 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);
253b146b01cSBarry Smith   }
254b146b01cSBarry Smith   if (map->N > 0 && map->bs > 1) {
255ec4d677dSStefano 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);
256b146b01cSBarry Smith   }
257b146b01cSBarry Smith 
25869ce434fSBarry Smith   ierr = MPI_Comm_size(map->comm, &size);CHKERRQ(ierr);
25969ce434fSBarry Smith   ierr = MPI_Comm_rank(map->comm, &rank);CHKERRQ(ierr);
26033d57670SJed Brown   if (map->n > 0) map->n = map->n/PetscAbs(map->bs);
26133d57670SJed Brown   if (map->N > 0) map->N = map->N/PetscAbs(map->bs);
26269ce434fSBarry Smith   ierr = PetscSplitOwnership(map->comm,&map->n,&map->N);CHKERRQ(ierr);
26333d57670SJed Brown   map->n = map->n*PetscAbs(map->bs);
26433d57670SJed Brown   map->N = map->N*PetscAbs(map->bs);
26569ce434fSBarry Smith   if (!map->range) {
266854ce69bSBarry Smith     ierr = PetscMalloc1(size+1, &map->range);CHKERRQ(ierr);
26769ce434fSBarry Smith   }
26869ce434fSBarry Smith   ierr = MPI_Allgather(&map->n, 1, MPIU_INT, map->range+1, 1, MPIU_INT, map->comm);CHKERRQ(ierr);
26969ce434fSBarry Smith 
27069ce434fSBarry Smith   map->range[0] = 0;
27169ce434fSBarry Smith   for (p = 2; p <= size; p++) map->range[p] += map->range[p-1];
27269ce434fSBarry Smith 
27369ce434fSBarry Smith   map->rstart = map->range[rank];
27469ce434fSBarry Smith   map->rend   = map->range[rank+1];
275ca5434daSLawrence Mitchell 
276ca5434daSLawrence Mitchell   /* lock the layout */
277ca5434daSLawrence Mitchell   map->setupcalled = PETSC_TRUE;
278ca5434daSLawrence Mitchell   map->oldn = map->n;
279ca5434daSLawrence Mitchell   map->oldN = map->N;
280ca5434daSLawrence Mitchell   map->oldbs = map->bs;
28169ce434fSBarry Smith   PetscFunctionReturn(0);
28269ce434fSBarry Smith }
28369ce434fSBarry Smith 
284c3002683SMatthew G. Knepley /*@
28569ce434fSBarry Smith   PetscLayoutDuplicate - creates a new PetscLayout with the same information as a given one. If the PetscLayout already exists it is destroyed first.
28669ce434fSBarry Smith 
28769ce434fSBarry Smith   Collective on PetscLayout
28869ce434fSBarry Smith 
28969ce434fSBarry Smith   Input Parameter:
29069ce434fSBarry Smith . in - input PetscLayout to be duplicated
29169ce434fSBarry Smith 
29269ce434fSBarry Smith   Output Parameter:
29369ce434fSBarry Smith . out - the copy
29469ce434fSBarry Smith 
29569ce434fSBarry Smith   Level: developer
29669ce434fSBarry Smith 
29795452b02SPatrick Sanan   Notes:
29895452b02SPatrick Sanan     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
29969ce434fSBarry Smith 
30069ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutReference()
30169ce434fSBarry Smith @*/
30269ce434fSBarry Smith PetscErrorCode PetscLayoutDuplicate(PetscLayout in,PetscLayout *out)
30369ce434fSBarry Smith {
30469ce434fSBarry Smith   PetscMPIInt    size;
30569ce434fSBarry Smith   PetscErrorCode ierr;
30669ce434fSBarry Smith   MPI_Comm       comm = in->comm;
30769ce434fSBarry Smith 
30869ce434fSBarry Smith   PetscFunctionBegin;
30969ce434fSBarry Smith   ierr = PetscLayoutDestroy(out);CHKERRQ(ierr);
31069ce434fSBarry Smith   ierr = PetscLayoutCreate(comm,out);CHKERRQ(ierr);
31169ce434fSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
31269ce434fSBarry Smith   ierr = PetscMemcpy(*out,in,sizeof(struct _n_PetscLayout));CHKERRQ(ierr);
313c168f6d8SVaclav Hapla   if (in->range) {
314854ce69bSBarry Smith     ierr = PetscMalloc1(size+1,&(*out)->range);CHKERRQ(ierr);
315580bdb30SBarry Smith     ierr = PetscArraycpy((*out)->range,in->range,size+1);CHKERRQ(ierr);
316c168f6d8SVaclav Hapla   }
31769ce434fSBarry Smith 
31869ce434fSBarry Smith   (*out)->refcnt = 0;
31969ce434fSBarry Smith   PetscFunctionReturn(0);
32069ce434fSBarry Smith }
32169ce434fSBarry Smith 
322c3002683SMatthew G. Knepley /*@
32369ce434fSBarry Smith   PetscLayoutReference - Causes a PETSc Vec or Mat to share a PetscLayout with one that already exists. Used by Vec/MatDuplicate_XXX()
32469ce434fSBarry Smith 
32569ce434fSBarry Smith   Collective on PetscLayout
32669ce434fSBarry Smith 
32769ce434fSBarry Smith   Input Parameter:
32869ce434fSBarry Smith . in - input PetscLayout to be copied
32969ce434fSBarry Smith 
33069ce434fSBarry Smith   Output Parameter:
33169ce434fSBarry Smith . out - the reference location
33269ce434fSBarry Smith 
33369ce434fSBarry Smith   Level: developer
33469ce434fSBarry Smith 
33595452b02SPatrick Sanan   Notes:
33695452b02SPatrick Sanan     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
33769ce434fSBarry Smith 
33869ce434fSBarry Smith   If the out location already contains a PetscLayout it is destroyed
33969ce434fSBarry Smith 
34069ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
34169ce434fSBarry Smith @*/
34269ce434fSBarry Smith PetscErrorCode PetscLayoutReference(PetscLayout in,PetscLayout *out)
34369ce434fSBarry Smith {
34469ce434fSBarry Smith   PetscErrorCode ierr;
34569ce434fSBarry Smith 
34669ce434fSBarry Smith   PetscFunctionBegin;
34769ce434fSBarry Smith   in->refcnt++;
34869ce434fSBarry Smith   ierr = PetscLayoutDestroy(out);CHKERRQ(ierr);
34969ce434fSBarry Smith   *out = in;
35069ce434fSBarry Smith   PetscFunctionReturn(0);
35169ce434fSBarry Smith }
35269ce434fSBarry Smith 
353c3002683SMatthew G. Knepley /*@
35469ce434fSBarry Smith   PetscLayoutSetISLocalToGlobalMapping - sets a ISLocalGlobalMapping into a PetscLayout
35569ce434fSBarry Smith 
35669ce434fSBarry Smith   Collective on PetscLayout
35769ce434fSBarry Smith 
35869ce434fSBarry Smith   Input Parameter:
35969ce434fSBarry Smith + in - input PetscLayout
36069ce434fSBarry Smith - ltog - the local to global mapping
36169ce434fSBarry Smith 
36269ce434fSBarry Smith 
36369ce434fSBarry Smith   Level: developer
36469ce434fSBarry Smith 
36595452b02SPatrick Sanan   Notes:
36695452b02SPatrick Sanan     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
36769ce434fSBarry Smith 
36869ce434fSBarry Smith   If the ltog location already contains a PetscLayout it is destroyed
36969ce434fSBarry Smith 
370a188d78dSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
37169ce434fSBarry Smith @*/
37269ce434fSBarry Smith PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in,ISLocalToGlobalMapping ltog)
37369ce434fSBarry Smith {
37469ce434fSBarry Smith   PetscErrorCode ierr;
37545b6f7e9SBarry Smith   PetscInt       bs;
37669ce434fSBarry Smith 
37769ce434fSBarry Smith   PetscFunctionBegin;
37845b6f7e9SBarry Smith   ierr = ISLocalToGlobalMappingGetBlockSize(ltog,&bs);CHKERRQ(ierr);
37937461477SLawrence 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);
38069ce434fSBarry Smith   ierr = PetscObjectReference((PetscObject)ltog);CHKERRQ(ierr);
38169ce434fSBarry Smith   ierr = ISLocalToGlobalMappingDestroy(&in->mapping);CHKERRQ(ierr);
38269ce434fSBarry Smith   in->mapping = ltog;
38369ce434fSBarry Smith   PetscFunctionReturn(0);
38469ce434fSBarry Smith }
38569ce434fSBarry Smith 
386c3002683SMatthew G. Knepley /*@
38769ce434fSBarry Smith   PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object.
38869ce434fSBarry Smith 
38969ce434fSBarry Smith   Collective on PetscLayout
39069ce434fSBarry Smith 
39169ce434fSBarry Smith   Input Parameters:
39269ce434fSBarry Smith + map - pointer to the map
39369ce434fSBarry Smith - n - the local size
39469ce434fSBarry Smith 
39569ce434fSBarry Smith   Level: developer
39669ce434fSBarry Smith 
39769ce434fSBarry Smith   Notes:
39869ce434fSBarry Smith   Call this after the call to PetscLayoutCreate()
39969ce434fSBarry Smith 
40069ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
40169ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
40269ce434fSBarry Smith @*/
40369ce434fSBarry Smith PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map,PetscInt n)
40469ce434fSBarry Smith {
40569ce434fSBarry Smith   PetscFunctionBegin;
40669ce434fSBarry 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);
40769ce434fSBarry Smith   map->n = n;
40869ce434fSBarry Smith   PetscFunctionReturn(0);
40969ce434fSBarry Smith }
41069ce434fSBarry Smith 
41169ce434fSBarry Smith /*@C
41269ce434fSBarry Smith      PetscLayoutGetLocalSize - Gets the local size for a PetscLayout object.
41369ce434fSBarry Smith 
41469ce434fSBarry Smith     Not Collective
41569ce434fSBarry Smith 
41669ce434fSBarry Smith    Input Parameters:
41769ce434fSBarry Smith .    map - pointer to the map
41869ce434fSBarry Smith 
41969ce434fSBarry Smith    Output Parameters:
42069ce434fSBarry Smith .    n - the local size
42169ce434fSBarry Smith 
42269ce434fSBarry Smith    Level: developer
42369ce434fSBarry Smith 
42469ce434fSBarry Smith     Notes:
42569ce434fSBarry Smith        Call this after the call to PetscLayoutSetUp()
42669ce434fSBarry Smith 
42769ce434fSBarry Smith     Fortran Notes:
42869ce434fSBarry Smith       Not available from Fortran
42969ce434fSBarry Smith 
43069ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
43169ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
43269ce434fSBarry Smith 
43369ce434fSBarry Smith @*/
43469ce434fSBarry Smith PetscErrorCode  PetscLayoutGetLocalSize(PetscLayout map,PetscInt *n)
43569ce434fSBarry Smith {
43669ce434fSBarry Smith   PetscFunctionBegin;
43769ce434fSBarry Smith   *n = map->n;
43869ce434fSBarry Smith   PetscFunctionReturn(0);
43969ce434fSBarry Smith }
44069ce434fSBarry Smith 
441c3002683SMatthew G. Knepley /*@
44269ce434fSBarry Smith   PetscLayoutSetSize - Sets the global size for a PetscLayout object.
44369ce434fSBarry Smith 
44469ce434fSBarry Smith   Logically Collective on PetscLayout
44569ce434fSBarry Smith 
44669ce434fSBarry Smith   Input Parameters:
44769ce434fSBarry Smith + map - pointer to the map
44869ce434fSBarry Smith - n - the global size
44969ce434fSBarry Smith 
45069ce434fSBarry Smith   Level: developer
45169ce434fSBarry Smith 
45269ce434fSBarry Smith   Notes:
45369ce434fSBarry Smith   Call this after the call to PetscLayoutCreate()
45469ce434fSBarry Smith 
45569ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
45669ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
45769ce434fSBarry Smith @*/
45869ce434fSBarry Smith PetscErrorCode PetscLayoutSetSize(PetscLayout map,PetscInt n)
45969ce434fSBarry Smith {
46069ce434fSBarry Smith   PetscFunctionBegin;
46169ce434fSBarry Smith   map->N = n;
46269ce434fSBarry Smith   PetscFunctionReturn(0);
46369ce434fSBarry Smith }
46469ce434fSBarry Smith 
465c3002683SMatthew G. Knepley /*@
46669ce434fSBarry Smith   PetscLayoutGetSize - Gets the global size for a PetscLayout object.
46769ce434fSBarry Smith 
46869ce434fSBarry Smith   Not Collective
46969ce434fSBarry Smith 
47069ce434fSBarry Smith   Input Parameters:
47169ce434fSBarry Smith . map - pointer to the map
47269ce434fSBarry Smith 
47369ce434fSBarry Smith   Output Parameters:
47469ce434fSBarry Smith . n - the global size
47569ce434fSBarry Smith 
47669ce434fSBarry Smith   Level: developer
47769ce434fSBarry Smith 
47869ce434fSBarry Smith   Notes:
47969ce434fSBarry Smith   Call this after the call to PetscLayoutSetUp()
48069ce434fSBarry Smith 
48169ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
48269ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
48369ce434fSBarry Smith @*/
48469ce434fSBarry Smith PetscErrorCode PetscLayoutGetSize(PetscLayout map,PetscInt *n)
48569ce434fSBarry Smith {
48669ce434fSBarry Smith   PetscFunctionBegin;
48769ce434fSBarry Smith   *n = map->N;
48869ce434fSBarry Smith   PetscFunctionReturn(0);
48969ce434fSBarry Smith }
49069ce434fSBarry Smith 
491c3002683SMatthew G. Knepley /*@
49269ce434fSBarry Smith   PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object.
49369ce434fSBarry Smith 
49469ce434fSBarry Smith   Logically Collective on PetscLayout
49569ce434fSBarry Smith 
49669ce434fSBarry Smith   Input Parameters:
49769ce434fSBarry Smith + map - pointer to the map
49869ce434fSBarry Smith - bs - the size
49969ce434fSBarry Smith 
50069ce434fSBarry Smith   Level: developer
50169ce434fSBarry Smith 
50269ce434fSBarry Smith   Notes:
50369ce434fSBarry Smith   Call this after the call to PetscLayoutCreate()
50469ce434fSBarry Smith 
50569ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
50669ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
50769ce434fSBarry Smith @*/
50869ce434fSBarry Smith PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs)
50969ce434fSBarry Smith {
51069ce434fSBarry Smith   PetscFunctionBegin;
51169bbac97SJed Brown   if (bs < 0) PetscFunctionReturn(0);
512299e779cSStefano 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);
513565245c5SBarry Smith   if (map->mapping) {
514705e6b8bSstefano_zampini     PetscInt       obs;
515565245c5SBarry Smith     PetscErrorCode ierr;
516565245c5SBarry Smith 
517705e6b8bSstefano_zampini     ierr = ISLocalToGlobalMappingGetBlockSize(map->mapping,&obs);CHKERRQ(ierr);
518705e6b8bSstefano_zampini     if (obs > 1) {
51963fa5c83Sstefano_zampini       ierr = ISLocalToGlobalMappingSetBlockSize(map->mapping,bs);CHKERRQ(ierr);
520565245c5SBarry Smith     }
521705e6b8bSstefano_zampini   }
52269ce434fSBarry Smith   map->bs = bs;
52369ce434fSBarry Smith   PetscFunctionReturn(0);
52469ce434fSBarry Smith }
52569ce434fSBarry Smith 
526c3002683SMatthew G. Knepley /*@
52769ce434fSBarry Smith   PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object.
52869ce434fSBarry Smith 
52969ce434fSBarry Smith   Not Collective
53069ce434fSBarry Smith 
53169ce434fSBarry Smith   Input Parameters:
53269ce434fSBarry Smith . map - pointer to the map
53369ce434fSBarry Smith 
53469ce434fSBarry Smith   Output Parameters:
53569ce434fSBarry Smith . bs - the size
53669ce434fSBarry Smith 
53769ce434fSBarry Smith   Level: developer
53869ce434fSBarry Smith 
53969ce434fSBarry Smith   Notes:
54069ce434fSBarry Smith   Call this after the call to PetscLayoutSetUp()
54169ce434fSBarry Smith 
54269ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
54369ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize()
54469ce434fSBarry Smith @*/
54569ce434fSBarry Smith PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs)
54669ce434fSBarry Smith {
54769ce434fSBarry Smith   PetscFunctionBegin;
54833d57670SJed Brown   *bs = PetscAbs(map->bs);
54969ce434fSBarry Smith   PetscFunctionReturn(0);
55069ce434fSBarry Smith }
55169ce434fSBarry Smith 
552c3002683SMatthew G. Knepley /*@
55369ce434fSBarry Smith   PetscLayoutGetRange - gets the range of values owned by this process
55469ce434fSBarry Smith 
55569ce434fSBarry Smith   Not Collective
55669ce434fSBarry Smith 
55769ce434fSBarry Smith   Input Parameters:
55869ce434fSBarry Smith . map - pointer to the map
55969ce434fSBarry Smith 
56069ce434fSBarry Smith   Output Parameters:
56169ce434fSBarry Smith + rstart - first index owned by this process
56269ce434fSBarry Smith - rend   - one more than the last index owned by this process
56369ce434fSBarry Smith 
56469ce434fSBarry Smith   Level: developer
56569ce434fSBarry Smith 
56669ce434fSBarry Smith   Notes:
56769ce434fSBarry Smith   Call this after the call to PetscLayoutSetUp()
56869ce434fSBarry Smith 
56969ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
57069ce434fSBarry Smith           PetscLayoutGetSize(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
57169ce434fSBarry Smith @*/
57269ce434fSBarry Smith PetscErrorCode PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend)
57369ce434fSBarry Smith {
57469ce434fSBarry Smith   PetscFunctionBegin;
57569ce434fSBarry Smith   if (rstart) *rstart = map->rstart;
57669ce434fSBarry Smith   if (rend)   *rend   = map->rend;
57769ce434fSBarry Smith   PetscFunctionReturn(0);
57869ce434fSBarry Smith }
57969ce434fSBarry Smith 
58069ce434fSBarry Smith /*@C
58169ce434fSBarry Smith      PetscLayoutGetRanges - gets the range of values owned by all processes
58269ce434fSBarry Smith 
58369ce434fSBarry Smith     Not Collective
58469ce434fSBarry Smith 
58569ce434fSBarry Smith    Input Parameters:
58669ce434fSBarry Smith .    map - pointer to the map
58769ce434fSBarry Smith 
58869ce434fSBarry Smith    Output Parameters:
58969ce434fSBarry Smith .    range - start of each processors range of indices (the final entry is one more then the
59069ce434fSBarry Smith              last index on the last process)
59169ce434fSBarry Smith 
59269ce434fSBarry Smith    Level: developer
59369ce434fSBarry Smith 
59469ce434fSBarry Smith     Notes:
59569ce434fSBarry Smith        Call this after the call to PetscLayoutSetUp()
59669ce434fSBarry Smith 
59769ce434fSBarry Smith     Fortran Notes:
59869ce434fSBarry Smith       Not available from Fortran
59969ce434fSBarry Smith 
60069ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
60169ce434fSBarry Smith           PetscLayoutGetSize(), PetscLayoutGetRange(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
60269ce434fSBarry Smith 
60369ce434fSBarry Smith @*/
60469ce434fSBarry Smith PetscErrorCode  PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[])
60569ce434fSBarry Smith {
60669ce434fSBarry Smith   PetscFunctionBegin;
60769ce434fSBarry Smith   *range = map->range;
60869ce434fSBarry Smith   PetscFunctionReturn(0);
60969ce434fSBarry Smith }
61069ce434fSBarry Smith 
61169ce434fSBarry Smith /*@C
612*f26271d2SStefano Zampini    PetscLayoutsCreateSF - Creates a parallel star forest mapping two PetscLayout objects
613*f26271d2SStefano Zampini 
614*f26271d2SStefano Zampini    Collective
615*f26271d2SStefano Zampini 
616*f26271d2SStefano Zampini    Input Arguments:
617*f26271d2SStefano Zampini +  rmap - PetscLayout defining the global root space
618*f26271d2SStefano Zampini -  lmap - PetscLayout defining the global leaf space
619*f26271d2SStefano Zampini 
620*f26271d2SStefano Zampini    Output Arguments:
621*f26271d2SStefano Zampini .  sf - The parallel star forest
622*f26271d2SStefano Zampini 
623*f26271d2SStefano Zampini    Level: intermediate
624*f26271d2SStefano Zampini 
625*f26271d2SStefano Zampini .seealso: PetscSFCreate(), PetscLayoutCreate(), PetscSFSetGraphLayout()
626*f26271d2SStefano Zampini @*/
627*f26271d2SStefano Zampini PetscErrorCode PetscLayoutsCreateSF(PetscLayout rmap, PetscLayout lmap, PetscSF* sf)
628*f26271d2SStefano Zampini {
629*f26271d2SStefano Zampini   PetscErrorCode ierr;
630*f26271d2SStefano Zampini   PetscInt       i,nroots,nleaves = 0;
631*f26271d2SStefano Zampini   PetscInt       rN, lst, len;
632*f26271d2SStefano Zampini   PetscMPIInt    owner = -1;
633*f26271d2SStefano Zampini   PetscSFNode    *remote;
634*f26271d2SStefano Zampini   MPI_Comm       rcomm = rmap->comm;
635*f26271d2SStefano Zampini   MPI_Comm       lcomm = lmap->comm;
636*f26271d2SStefano Zampini   PetscMPIInt    flg;
637*f26271d2SStefano Zampini 
638*f26271d2SStefano Zampini   PetscFunctionBegin;
639*f26271d2SStefano Zampini   PetscValidPointer(sf,3);
640*f26271d2SStefano Zampini   if (!rmap->setupcalled) SETERRQ(rcomm,PETSC_ERR_ARG_WRONGSTATE,"Root layout not setup");
641*f26271d2SStefano Zampini   if (!lmap->setupcalled) SETERRQ(lcomm,PETSC_ERR_ARG_WRONGSTATE,"Leaf layout not setup");
642*f26271d2SStefano Zampini   ierr = MPI_Comm_compare(rcomm,lcomm,&flg);CHKERRQ(ierr);
643*f26271d2SStefano Zampini   if (flg != MPI_CONGRUENT && flg != MPI_IDENT) SETERRQ(rcomm,PETSC_ERR_SUP,"cannot map two layouts with non-matching communicators");
644*f26271d2SStefano Zampini   ierr = PetscSFCreate(rcomm,sf);CHKERRQ(ierr);
645*f26271d2SStefano Zampini   ierr = PetscLayoutGetLocalSize(rmap,&nroots);CHKERRQ(ierr);
646*f26271d2SStefano Zampini   ierr = PetscLayoutGetSize(rmap,&rN);CHKERRQ(ierr);
647*f26271d2SStefano Zampini   ierr = PetscLayoutGetRange(lmap,&lst,&len);CHKERRQ(ierr);
648*f26271d2SStefano Zampini   ierr = PetscMalloc1(len-lst,&remote);CHKERRQ(ierr);
649*f26271d2SStefano Zampini   for (i = lst; i < len && i < rN; i++) {
650*f26271d2SStefano Zampini     if (owner < -1 || i >= rmap->range[owner+1]) {
651*f26271d2SStefano Zampini       ierr = PetscLayoutFindOwner(rmap,i,&owner);CHKERRQ(ierr);
652*f26271d2SStefano Zampini     }
653*f26271d2SStefano Zampini     remote[nleaves].rank  = owner;
654*f26271d2SStefano Zampini     remote[nleaves].index = i - rmap->range[owner];
655*f26271d2SStefano Zampini     nleaves++;
656*f26271d2SStefano Zampini   }
657*f26271d2SStefano Zampini   ierr = PetscSFSetGraph(*sf,nroots,nleaves,NULL,PETSC_OWN_POINTER,remote,PETSC_COPY_VALUES);CHKERRQ(ierr);
658*f26271d2SStefano Zampini   ierr = PetscFree(remote);CHKERRQ(ierr);
659*f26271d2SStefano Zampini   PetscFunctionReturn(0);
660*f26271d2SStefano Zampini }
661*f26271d2SStefano Zampini 
662*f26271d2SStefano Zampini /*@C
66369ce434fSBarry Smith    PetscSFSetGraphLayout - Set a parallel star forest via global indices and a PetscLayout
66469ce434fSBarry Smith 
66569ce434fSBarry Smith    Collective
66669ce434fSBarry Smith 
66769ce434fSBarry Smith    Input Arguments:
66869ce434fSBarry Smith +  sf - star forest
66969ce434fSBarry Smith .  layout - PetscLayout defining the global space
67069ce434fSBarry Smith .  nleaves - number of leaf vertices on the current process, each of these references a root on any process
67169ce434fSBarry Smith .  ilocal - locations of leaves in leafdata buffers, pass NULL for contiguous storage
672cf79137fSStefano Zampini .  localmode - copy mode for ilocal
67369ce434fSBarry Smith -  iremote - remote locations of root vertices for each leaf on the current process
67469ce434fSBarry Smith 
67569ce434fSBarry Smith    Level: intermediate
67669ce434fSBarry Smith 
677cf79137fSStefano Zampini    Developers Note: Local indices which are the identity permutation in the range [0,nleaves) are discarded as they
678cf79137fSStefano Zampini    encode contiguous storage. In such case, if localmode is PETSC_OWN_POINTER, the memory is deallocated as it is not
679cf79137fSStefano Zampini    needed
680cf79137fSStefano Zampini 
68169ce434fSBarry Smith .seealso: PetscSFCreate(), PetscSFView(), PetscSFSetGraph(), PetscSFGetGraph()
68269ce434fSBarry Smith @*/
68369ce434fSBarry Smith PetscErrorCode PetscSFSetGraphLayout(PetscSF sf,PetscLayout layout,PetscInt nleaves,const PetscInt *ilocal,PetscCopyMode localmode,const PetscInt *iremote)
68469ce434fSBarry Smith {
68569ce434fSBarry Smith   PetscErrorCode ierr;
68669ce434fSBarry Smith   PetscInt       i,nroots;
68769ce434fSBarry Smith   PetscSFNode    *remote;
68869ce434fSBarry Smith 
68969ce434fSBarry Smith   PetscFunctionBegin;
69069ce434fSBarry Smith   ierr = PetscLayoutGetLocalSize(layout,&nroots);CHKERRQ(ierr);
691785e854fSJed Brown   ierr = PetscMalloc1(nleaves,&remote);CHKERRQ(ierr);
69269ce434fSBarry Smith   for (i=0; i<nleaves; i++) {
693131c27b5Sprj-     PetscMPIInt owner = -1;
69469ce434fSBarry Smith     ierr = PetscLayoutFindOwner(layout,iremote[i],&owner);CHKERRQ(ierr);
69569ce434fSBarry Smith     remote[i].rank  = owner;
69669ce434fSBarry Smith     remote[i].index = iremote[i] - layout->range[owner];
69769ce434fSBarry Smith   }
69869ce434fSBarry Smith   ierr = PetscSFSetGraph(sf,nroots,nleaves,ilocal,localmode,remote,PETSC_OWN_POINTER);CHKERRQ(ierr);
69969ce434fSBarry Smith   PetscFunctionReturn(0);
70069ce434fSBarry Smith }
70169ce434fSBarry Smith 
702f92d6284SStefano Zampini /*@
703f92d6284SStefano Zampini   PetscLayoutCompare - Compares two layouts
704f92d6284SStefano Zampini 
705f92d6284SStefano Zampini   Not Collective
706f92d6284SStefano Zampini 
707f92d6284SStefano Zampini   Input Parameters:
708d11c674dSStefano Zampini + mapa - pointer to the first map
709f92d6284SStefano Zampini - mapb - pointer to the second map
710f92d6284SStefano Zampini 
711f92d6284SStefano Zampini   Output Parameters:
712f92d6284SStefano Zampini . congruent - PETSC_TRUE if the two layouts are congruent, PETSC_FALSE otherwise
713f92d6284SStefano Zampini 
714f92d6284SStefano Zampini   Level: beginner
715f92d6284SStefano Zampini 
716f92d6284SStefano Zampini   Notes:
717f92d6284SStefano Zampini 
718f92d6284SStefano Zampini .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
719f92d6284SStefano Zampini           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
720f92d6284SStefano Zampini @*/
721f92d6284SStefano Zampini PetscErrorCode PetscLayoutCompare(PetscLayout mapa,PetscLayout mapb,PetscBool *congruent)
722f92d6284SStefano Zampini {
723f92d6284SStefano Zampini   PetscErrorCode ierr;
724f92d6284SStefano Zampini   PetscMPIInt    sizea,sizeb;
725f92d6284SStefano Zampini 
726f92d6284SStefano Zampini   PetscFunctionBegin;
727f92d6284SStefano Zampini   *congruent = PETSC_FALSE;
728f92d6284SStefano Zampini   ierr = MPI_Comm_size(mapa->comm,&sizea);CHKERRQ(ierr);
729f92d6284SStefano Zampini   ierr = MPI_Comm_size(mapb->comm,&sizeb);CHKERRQ(ierr);
730f92d6284SStefano Zampini   if (mapa->N == mapb->N && mapa->range && mapb->range && sizea == sizeb) {
731580bdb30SBarry Smith     ierr = PetscArraycmp(mapa->range,mapb->range,sizea+1,congruent);CHKERRQ(ierr);
732f92d6284SStefano Zampini   }
733f92d6284SStefano Zampini   PetscFunctionReturn(0);
734f92d6284SStefano Zampini }
735a72d46e8SStefano Zampini 
736a72d46e8SStefano Zampini /* TODO: handle nooffprocentries like MatZeroRowsMapLocal_Private, since this code is the same */
737a72d46e8SStefano Zampini PetscErrorCode PetscLayoutMapLocal(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
738a72d46e8SStefano Zampini {
739a72d46e8SStefano Zampini   PetscInt      *owners = map->range;
740a72d46e8SStefano Zampini   PetscInt       n      = map->n;
741a72d46e8SStefano Zampini   PetscSF        sf;
742a72d46e8SStefano Zampini   PetscInt      *lidxs,*work = NULL;
743a72d46e8SStefano Zampini   PetscSFNode   *ridxs;
744131c27b5Sprj-   PetscMPIInt    rank, p = 0;
745131c27b5Sprj-   PetscInt       r, len = 0;
746a72d46e8SStefano Zampini   PetscErrorCode ierr;
747a72d46e8SStefano Zampini 
748a72d46e8SStefano Zampini   PetscFunctionBegin;
749a72d46e8SStefano Zampini   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
750a72d46e8SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs */
751a72d46e8SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
752a72d46e8SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
753a72d46e8SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
754a72d46e8SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
755a72d46e8SStefano Zampini   for (r = 0; r < N; ++r) {
756a72d46e8SStefano Zampini     const PetscInt idx = idxs[r];
757a72d46e8SStefano 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);
758a72d46e8SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
759a72d46e8SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
760a72d46e8SStefano Zampini     }
761a72d46e8SStefano Zampini     ridxs[r].rank = p;
762a72d46e8SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
763a72d46e8SStefano Zampini   }
764a72d46e8SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
765a72d46e8SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
766a72d46e8SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
767a72d46e8SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
768a72d46e8SStefano Zampini   if (ogidxs) { /* communicate global idxs */
769a72d46e8SStefano Zampini     PetscInt cum = 0,start,*work2;
770a72d46e8SStefano Zampini 
771a72d46e8SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
772a72d46e8SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
773a72d46e8SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
774a72d46e8SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
775a72d46e8SStefano Zampini     start -= cum;
776a72d46e8SStefano Zampini     cum = 0;
777a72d46e8SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
778a72d46e8SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
779a72d46e8SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
780a72d46e8SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
781a72d46e8SStefano Zampini   }
782a72d46e8SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
783a72d46e8SStefano Zampini   /* Compress and put in indices */
784a72d46e8SStefano Zampini   for (r = 0; r < n; ++r)
785a72d46e8SStefano Zampini     if (lidxs[r] >= 0) {
786a72d46e8SStefano Zampini       if (work) work[len] = work[r];
787a72d46e8SStefano Zampini       lidxs[len++] = r;
788a72d46e8SStefano Zampini     }
789a72d46e8SStefano Zampini   if (on) *on = len;
790a72d46e8SStefano Zampini   if (oidxs) *oidxs = lidxs;
791a72d46e8SStefano Zampini   if (ogidxs) *ogidxs = work;
792a72d46e8SStefano Zampini   PetscFunctionReturn(0);
793a72d46e8SStefano Zampini }
794