xref: /petsc/src/vec/is/utils/pmap.c (revision c168f6d8e6d113b97645dfd96fa277c9c2372c3a)
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
3169ce434fSBarry Smith   Optionally use any of the following:
32456fcb79SJed Brown 
33456fcb79SJed Brown + PetscLayoutGetSize(PetscLayout,PetscInt *);
34456fcb79SJed Brown . PetscLayoutGetLocalSize(PetscLayout,PetscInt *);
35456fcb79SJed Brown . PetscLayoutGetRange(PetscLayout,PetscInt *rstart,PetscInt *rend);
36456fcb79SJed Brown . PetscLayoutGetRanges(PetscLayout,const PetscInt *range[]);
37456fcb79SJed Brown - PetscLayoutDestroy(PetscLayout*);
3869ce434fSBarry Smith 
3969ce434fSBarry Smith   The PetscLayout object and methods are intended to be used in the PETSc Vec and Mat implementions; it is often not needed in
4069ce434fSBarry Smith   user codes unless you really gain something in their use.
4169ce434fSBarry Smith 
4269ce434fSBarry Smith .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
4369ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp()
4469ce434fSBarry Smith 
4569ce434fSBarry Smith @*/
4669ce434fSBarry Smith PetscErrorCode PetscLayoutCreate(MPI_Comm comm,PetscLayout *map)
4769ce434fSBarry Smith {
4869ce434fSBarry Smith   PetscErrorCode ierr;
4969ce434fSBarry Smith 
5069ce434fSBarry Smith   PetscFunctionBegin;
51b00a9115SJed Brown   ierr = PetscNew(map);CHKERRQ(ierr);
5269ce434fSBarry Smith 
5369ce434fSBarry Smith   (*map)->comm   = comm;
5469ce434fSBarry Smith   (*map)->bs     = -1;
5569ce434fSBarry Smith   (*map)->n      = -1;
5669ce434fSBarry Smith   (*map)->N      = -1;
57f92d6284SStefano Zampini   (*map)->range  = NULL;
5869ce434fSBarry Smith   (*map)->rstart = 0;
5969ce434fSBarry Smith   (*map)->rend   = 0;
6069ce434fSBarry Smith   PetscFunctionReturn(0);
6169ce434fSBarry Smith }
6269ce434fSBarry Smith 
63c3002683SMatthew G. Knepley /*@
6469ce434fSBarry Smith   PetscLayoutDestroy - Frees a map object and frees its range if that exists.
6569ce434fSBarry Smith 
66d083f849SBarry Smith   Collective
6769ce434fSBarry Smith 
6869ce434fSBarry Smith   Input Parameters:
6969ce434fSBarry Smith . map - the PetscLayout
7069ce434fSBarry Smith 
7169ce434fSBarry Smith   Level: developer
7269ce434fSBarry Smith 
73c3002683SMatthew G. Knepley   Note:
7469ce434fSBarry Smith   The PetscLayout object and methods are intended to be used in the PETSc Vec and Mat implementions; it is
7569ce434fSBarry Smith   recommended they not be used in user codes unless you really gain something in their use.
7669ce434fSBarry Smith 
7769ce434fSBarry Smith .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutCreate(),
7869ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp()
7969ce434fSBarry Smith 
8069ce434fSBarry Smith @*/
8169ce434fSBarry Smith PetscErrorCode PetscLayoutDestroy(PetscLayout *map)
8269ce434fSBarry Smith {
8369ce434fSBarry Smith   PetscErrorCode ierr;
8469ce434fSBarry Smith 
8569ce434fSBarry Smith   PetscFunctionBegin;
8669ce434fSBarry Smith   if (!*map) PetscFunctionReturn(0);
8769ce434fSBarry Smith   if (!(*map)->refcnt--) {
8869ce434fSBarry Smith     ierr = PetscFree((*map)->range);CHKERRQ(ierr);
8969ce434fSBarry Smith     ierr = ISLocalToGlobalMappingDestroy(&(*map)->mapping);CHKERRQ(ierr);
9069ce434fSBarry Smith     ierr = PetscFree((*map));CHKERRQ(ierr);
9169ce434fSBarry Smith   }
9269ce434fSBarry Smith   *map = NULL;
9369ce434fSBarry Smith   PetscFunctionReturn(0);
9469ce434fSBarry Smith }
9569ce434fSBarry Smith 
967b659617SVaclav Hapla static PetscErrorCode PetscLayoutSetUp_SizesFromRanges_Private(PetscLayout map)
977b659617SVaclav Hapla {
987b659617SVaclav Hapla   PetscMPIInt    rank,size;
997b659617SVaclav Hapla   PetscErrorCode ierr;
1007b659617SVaclav Hapla 
1017b659617SVaclav Hapla   PetscFunctionBegin;
1027b659617SVaclav Hapla   ierr = MPI_Comm_size(map->comm, &size);CHKERRQ(ierr);
1037b659617SVaclav Hapla   ierr = MPI_Comm_rank(map->comm, &rank);CHKERRQ(ierr);
1047b659617SVaclav Hapla   map->rstart = map->range[rank];
1057b659617SVaclav Hapla   map->rend   = map->range[rank+1];
1067b659617SVaclav Hapla   map->n      = map->rend - map->rstart;
1077b659617SVaclav Hapla   map->N      = map->range[size];
1087b659617SVaclav Hapla #if defined(PETSC_USE_DEBUG)
1097b659617SVaclav Hapla   /* just check that n, N and bs are consistent */
1107b659617SVaclav Hapla   {
1117b659617SVaclav Hapla     PetscInt tmp;
1127b659617SVaclav Hapla     ierr = MPIU_Allreduce(&map->n,&tmp,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
1137b659617SVaclav 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);
1147b659617SVaclav Hapla   }
1157b659617SVaclav Hapla   if (map->bs > 1) {
1167b659617SVaclav 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);
1177b659617SVaclav Hapla   }
1187b659617SVaclav Hapla   if (map->bs > 1) {
1197b659617SVaclav 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);
1207b659617SVaclav Hapla   }
1217b659617SVaclav Hapla #endif
1227b659617SVaclav Hapla   PetscFunctionReturn(0);
1237b659617SVaclav Hapla }
1247b659617SVaclav Hapla 
125c3002683SMatthew G. Knepley /*@
12669ce434fSBarry Smith   PetscLayoutSetUp - given a map where you have set either the global or local
12769ce434fSBarry Smith                      size sets up the map so that it may be used.
12869ce434fSBarry Smith 
129d083f849SBarry Smith   Collective
13069ce434fSBarry Smith 
13169ce434fSBarry Smith   Input Parameters:
13269ce434fSBarry Smith . map - pointer to the map
13369ce434fSBarry Smith 
13469ce434fSBarry Smith   Level: developer
13569ce434fSBarry Smith 
13695452b02SPatrick Sanan   Notes:
13795452b02SPatrick Sanan     Typical calling sequence
138c3002683SMatthew G. Knepley $ PetscLayoutCreate(MPI_Comm,PetscLayout *);
139c3002683SMatthew G. Knepley $ PetscLayoutSetBlockSize(PetscLayout,1);
140c3002683SMatthew G. Knepley $ PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both
141c3002683SMatthew G. Knepley $ PetscLayoutSetUp(PetscLayout);
142c3002683SMatthew G. Knepley $ PetscLayoutGetSize(PetscLayout,PetscInt *);
14369ce434fSBarry Smith 
1447b659617SVaclav Hapla   If range exists, and local size is not set, everything gets computed from the range.
14569ce434fSBarry Smith 
14669ce434fSBarry Smith   If the local size, global size are already set and range exists then this does nothing.
14769ce434fSBarry Smith 
14869ce434fSBarry Smith .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
14969ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutCreate()
15069ce434fSBarry Smith @*/
15169ce434fSBarry Smith PetscErrorCode PetscLayoutSetUp(PetscLayout map)
15269ce434fSBarry Smith {
15369ce434fSBarry Smith   PetscMPIInt    rank,size;
15469ce434fSBarry Smith   PetscInt       p;
15569ce434fSBarry Smith   PetscErrorCode ierr;
15669ce434fSBarry Smith 
15769ce434fSBarry Smith   PetscFunctionBegin;
15869ce434fSBarry Smith   if ((map->n >= 0) && (map->N >= 0) && (map->range)) PetscFunctionReturn(0);
1597b659617SVaclav Hapla   if (map->range && map->n < 0) {
1607b659617SVaclav Hapla     ierr = PetscLayoutSetUp_SizesFromRanges_Private(map);CHKERRQ(ierr);
1617b659617SVaclav Hapla     PetscFunctionReturn(0);
1627b659617SVaclav Hapla   }
16369ce434fSBarry Smith 
164b146b01cSBarry Smith   if (map->n > 0 && map->bs > 1) {
165ec4d677dSStefano 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);
166b146b01cSBarry Smith   }
167b146b01cSBarry Smith   if (map->N > 0 && map->bs > 1) {
168ec4d677dSStefano 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);
169b146b01cSBarry Smith   }
170b146b01cSBarry Smith 
17169ce434fSBarry Smith   ierr = MPI_Comm_size(map->comm, &size);CHKERRQ(ierr);
17269ce434fSBarry Smith   ierr = MPI_Comm_rank(map->comm, &rank);CHKERRQ(ierr);
17333d57670SJed Brown   if (map->n > 0) map->n = map->n/PetscAbs(map->bs);
17433d57670SJed Brown   if (map->N > 0) map->N = map->N/PetscAbs(map->bs);
17569ce434fSBarry Smith   ierr = PetscSplitOwnership(map->comm,&map->n,&map->N);CHKERRQ(ierr);
17633d57670SJed Brown   map->n = map->n*PetscAbs(map->bs);
17733d57670SJed Brown   map->N = map->N*PetscAbs(map->bs);
17869ce434fSBarry Smith   if (!map->range) {
179854ce69bSBarry Smith     ierr = PetscMalloc1(size+1, &map->range);CHKERRQ(ierr);
18069ce434fSBarry Smith   }
18169ce434fSBarry Smith   ierr = MPI_Allgather(&map->n, 1, MPIU_INT, map->range+1, 1, MPIU_INT, map->comm);CHKERRQ(ierr);
18269ce434fSBarry Smith 
18369ce434fSBarry Smith   map->range[0] = 0;
18469ce434fSBarry Smith   for (p = 2; p <= size; p++) map->range[p] += map->range[p-1];
18569ce434fSBarry Smith 
18669ce434fSBarry Smith   map->rstart = map->range[rank];
18769ce434fSBarry Smith   map->rend   = map->range[rank+1];
18869ce434fSBarry Smith   PetscFunctionReturn(0);
18969ce434fSBarry Smith }
19069ce434fSBarry Smith 
191c3002683SMatthew G. Knepley /*@
19269ce434fSBarry Smith   PetscLayoutDuplicate - creates a new PetscLayout with the same information as a given one. If the PetscLayout already exists it is destroyed first.
19369ce434fSBarry Smith 
19469ce434fSBarry Smith   Collective on PetscLayout
19569ce434fSBarry Smith 
19669ce434fSBarry Smith   Input Parameter:
19769ce434fSBarry Smith . in - input PetscLayout to be duplicated
19869ce434fSBarry Smith 
19969ce434fSBarry Smith   Output Parameter:
20069ce434fSBarry Smith . out - the copy
20169ce434fSBarry Smith 
20269ce434fSBarry Smith   Level: developer
20369ce434fSBarry Smith 
20495452b02SPatrick Sanan   Notes:
20595452b02SPatrick Sanan     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
20669ce434fSBarry Smith 
20769ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutReference()
20869ce434fSBarry Smith @*/
20969ce434fSBarry Smith PetscErrorCode PetscLayoutDuplicate(PetscLayout in,PetscLayout *out)
21069ce434fSBarry Smith {
21169ce434fSBarry Smith   PetscMPIInt    size;
21269ce434fSBarry Smith   PetscErrorCode ierr;
21369ce434fSBarry Smith   MPI_Comm       comm = in->comm;
21469ce434fSBarry Smith 
21569ce434fSBarry Smith   PetscFunctionBegin;
21669ce434fSBarry Smith   ierr = PetscLayoutDestroy(out);CHKERRQ(ierr);
21769ce434fSBarry Smith   ierr = PetscLayoutCreate(comm,out);CHKERRQ(ierr);
21869ce434fSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
21969ce434fSBarry Smith   ierr = PetscMemcpy(*out,in,sizeof(struct _n_PetscLayout));CHKERRQ(ierr);
220*c168f6d8SVaclav Hapla   if (in->range) {
221854ce69bSBarry Smith     ierr = PetscMalloc1(size+1,&(*out)->range);CHKERRQ(ierr);
222580bdb30SBarry Smith     ierr = PetscArraycpy((*out)->range,in->range,size+1);CHKERRQ(ierr);
223*c168f6d8SVaclav Hapla   }
22469ce434fSBarry Smith 
22569ce434fSBarry Smith   (*out)->refcnt = 0;
22669ce434fSBarry Smith   PetscFunctionReturn(0);
22769ce434fSBarry Smith }
22869ce434fSBarry Smith 
229c3002683SMatthew G. Knepley /*@
23069ce434fSBarry Smith   PetscLayoutReference - Causes a PETSc Vec or Mat to share a PetscLayout with one that already exists. Used by Vec/MatDuplicate_XXX()
23169ce434fSBarry Smith 
23269ce434fSBarry Smith   Collective on PetscLayout
23369ce434fSBarry Smith 
23469ce434fSBarry Smith   Input Parameter:
23569ce434fSBarry Smith . in - input PetscLayout to be copied
23669ce434fSBarry Smith 
23769ce434fSBarry Smith   Output Parameter:
23869ce434fSBarry Smith . out - the reference location
23969ce434fSBarry Smith 
24069ce434fSBarry Smith   Level: developer
24169ce434fSBarry Smith 
24295452b02SPatrick Sanan   Notes:
24395452b02SPatrick Sanan     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
24469ce434fSBarry Smith 
24569ce434fSBarry Smith   If the out location already contains a PetscLayout it is destroyed
24669ce434fSBarry Smith 
24769ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
24869ce434fSBarry Smith @*/
24969ce434fSBarry Smith PetscErrorCode PetscLayoutReference(PetscLayout in,PetscLayout *out)
25069ce434fSBarry Smith {
25169ce434fSBarry Smith   PetscErrorCode ierr;
25269ce434fSBarry Smith 
25369ce434fSBarry Smith   PetscFunctionBegin;
25469ce434fSBarry Smith   in->refcnt++;
25569ce434fSBarry Smith   ierr = PetscLayoutDestroy(out);CHKERRQ(ierr);
25669ce434fSBarry Smith   *out = in;
25769ce434fSBarry Smith   PetscFunctionReturn(0);
25869ce434fSBarry Smith }
25969ce434fSBarry Smith 
260c3002683SMatthew G. Knepley /*@
26169ce434fSBarry Smith   PetscLayoutSetISLocalToGlobalMapping - sets a ISLocalGlobalMapping into a PetscLayout
26269ce434fSBarry Smith 
26369ce434fSBarry Smith   Collective on PetscLayout
26469ce434fSBarry Smith 
26569ce434fSBarry Smith   Input Parameter:
26669ce434fSBarry Smith + in - input PetscLayout
26769ce434fSBarry Smith - ltog - the local to global mapping
26869ce434fSBarry Smith 
26969ce434fSBarry Smith 
27069ce434fSBarry Smith   Level: developer
27169ce434fSBarry Smith 
27295452b02SPatrick Sanan   Notes:
27395452b02SPatrick Sanan     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
27469ce434fSBarry Smith 
27569ce434fSBarry Smith   If the ltog location already contains a PetscLayout it is destroyed
27669ce434fSBarry Smith 
277a188d78dSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
27869ce434fSBarry Smith @*/
27969ce434fSBarry Smith PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in,ISLocalToGlobalMapping ltog)
28069ce434fSBarry Smith {
28169ce434fSBarry Smith   PetscErrorCode ierr;
28245b6f7e9SBarry Smith   PetscInt       bs;
28369ce434fSBarry Smith 
28469ce434fSBarry Smith   PetscFunctionBegin;
28545b6f7e9SBarry Smith   ierr = ISLocalToGlobalMappingGetBlockSize(ltog,&bs);CHKERRQ(ierr);
28637461477SLawrence 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);
28769ce434fSBarry Smith   ierr = PetscObjectReference((PetscObject)ltog);CHKERRQ(ierr);
28869ce434fSBarry Smith   ierr = ISLocalToGlobalMappingDestroy(&in->mapping);CHKERRQ(ierr);
28969ce434fSBarry Smith   in->mapping = ltog;
29069ce434fSBarry Smith   PetscFunctionReturn(0);
29169ce434fSBarry Smith }
29269ce434fSBarry Smith 
293c3002683SMatthew G. Knepley /*@
29469ce434fSBarry Smith   PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object.
29569ce434fSBarry Smith 
29669ce434fSBarry Smith   Collective on PetscLayout
29769ce434fSBarry Smith 
29869ce434fSBarry Smith   Input Parameters:
29969ce434fSBarry Smith + map - pointer to the map
30069ce434fSBarry Smith - n - the local size
30169ce434fSBarry Smith 
30269ce434fSBarry Smith   Level: developer
30369ce434fSBarry Smith 
30469ce434fSBarry Smith   Notes:
30569ce434fSBarry Smith   Call this after the call to PetscLayoutCreate()
30669ce434fSBarry Smith 
30769ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
30869ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
30969ce434fSBarry Smith @*/
31069ce434fSBarry Smith PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map,PetscInt n)
31169ce434fSBarry Smith {
31269ce434fSBarry Smith   PetscFunctionBegin;
31369ce434fSBarry 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);
31469ce434fSBarry Smith   map->n = n;
31569ce434fSBarry Smith   PetscFunctionReturn(0);
31669ce434fSBarry Smith }
31769ce434fSBarry Smith 
31869ce434fSBarry Smith /*@C
31969ce434fSBarry Smith      PetscLayoutGetLocalSize - Gets the local size for a PetscLayout object.
32069ce434fSBarry Smith 
32169ce434fSBarry Smith     Not Collective
32269ce434fSBarry Smith 
32369ce434fSBarry Smith    Input Parameters:
32469ce434fSBarry Smith .    map - pointer to the map
32569ce434fSBarry Smith 
32669ce434fSBarry Smith    Output Parameters:
32769ce434fSBarry Smith .    n - the local size
32869ce434fSBarry Smith 
32969ce434fSBarry Smith    Level: developer
33069ce434fSBarry Smith 
33169ce434fSBarry Smith     Notes:
33269ce434fSBarry Smith        Call this after the call to PetscLayoutSetUp()
33369ce434fSBarry Smith 
33469ce434fSBarry Smith     Fortran Notes:
33569ce434fSBarry Smith       Not available from Fortran
33669ce434fSBarry Smith 
33769ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
33869ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
33969ce434fSBarry Smith 
34069ce434fSBarry Smith @*/
34169ce434fSBarry Smith PetscErrorCode  PetscLayoutGetLocalSize(PetscLayout map,PetscInt *n)
34269ce434fSBarry Smith {
34369ce434fSBarry Smith   PetscFunctionBegin;
34469ce434fSBarry Smith   *n = map->n;
34569ce434fSBarry Smith   PetscFunctionReturn(0);
34669ce434fSBarry Smith }
34769ce434fSBarry Smith 
348c3002683SMatthew G. Knepley /*@
34969ce434fSBarry Smith   PetscLayoutSetSize - Sets the global size for a PetscLayout object.
35069ce434fSBarry Smith 
35169ce434fSBarry Smith   Logically Collective on PetscLayout
35269ce434fSBarry Smith 
35369ce434fSBarry Smith   Input Parameters:
35469ce434fSBarry Smith + map - pointer to the map
35569ce434fSBarry Smith - n - the global size
35669ce434fSBarry Smith 
35769ce434fSBarry Smith   Level: developer
35869ce434fSBarry Smith 
35969ce434fSBarry Smith   Notes:
36069ce434fSBarry Smith   Call this after the call to PetscLayoutCreate()
36169ce434fSBarry Smith 
36269ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
36369ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
36469ce434fSBarry Smith @*/
36569ce434fSBarry Smith PetscErrorCode PetscLayoutSetSize(PetscLayout map,PetscInt n)
36669ce434fSBarry Smith {
36769ce434fSBarry Smith   PetscFunctionBegin;
36869ce434fSBarry Smith   map->N = n;
36969ce434fSBarry Smith   PetscFunctionReturn(0);
37069ce434fSBarry Smith }
37169ce434fSBarry Smith 
372c3002683SMatthew G. Knepley /*@
37369ce434fSBarry Smith   PetscLayoutGetSize - Gets the global size for a PetscLayout object.
37469ce434fSBarry Smith 
37569ce434fSBarry Smith   Not Collective
37669ce434fSBarry Smith 
37769ce434fSBarry Smith   Input Parameters:
37869ce434fSBarry Smith . map - pointer to the map
37969ce434fSBarry Smith 
38069ce434fSBarry Smith   Output Parameters:
38169ce434fSBarry Smith . n - the global size
38269ce434fSBarry Smith 
38369ce434fSBarry Smith   Level: developer
38469ce434fSBarry Smith 
38569ce434fSBarry Smith   Notes:
38669ce434fSBarry Smith   Call this after the call to PetscLayoutSetUp()
38769ce434fSBarry Smith 
38869ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
38969ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
39069ce434fSBarry Smith @*/
39169ce434fSBarry Smith PetscErrorCode PetscLayoutGetSize(PetscLayout map,PetscInt *n)
39269ce434fSBarry Smith {
39369ce434fSBarry Smith   PetscFunctionBegin;
39469ce434fSBarry Smith   *n = map->N;
39569ce434fSBarry Smith   PetscFunctionReturn(0);
39669ce434fSBarry Smith }
39769ce434fSBarry Smith 
398c3002683SMatthew G. Knepley /*@
39969ce434fSBarry Smith   PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object.
40069ce434fSBarry Smith 
40169ce434fSBarry Smith   Logically Collective on PetscLayout
40269ce434fSBarry Smith 
40369ce434fSBarry Smith   Input Parameters:
40469ce434fSBarry Smith + map - pointer to the map
40569ce434fSBarry Smith - bs - the size
40669ce434fSBarry Smith 
40769ce434fSBarry Smith   Level: developer
40869ce434fSBarry Smith 
40969ce434fSBarry Smith   Notes:
41069ce434fSBarry Smith   Call this after the call to PetscLayoutCreate()
41169ce434fSBarry Smith 
41269ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
41369ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
41469ce434fSBarry Smith @*/
41569ce434fSBarry Smith PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs)
41669ce434fSBarry Smith {
41769ce434fSBarry Smith   PetscFunctionBegin;
41869bbac97SJed Brown   if (bs < 0) PetscFunctionReturn(0);
419299e779cSStefano 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);
420565245c5SBarry Smith   if (map->mapping) {
421705e6b8bSstefano_zampini     PetscInt       obs;
422565245c5SBarry Smith     PetscErrorCode ierr;
423565245c5SBarry Smith 
424705e6b8bSstefano_zampini     ierr = ISLocalToGlobalMappingGetBlockSize(map->mapping,&obs);CHKERRQ(ierr);
425705e6b8bSstefano_zampini     if (obs > 1) {
42663fa5c83Sstefano_zampini       ierr = ISLocalToGlobalMappingSetBlockSize(map->mapping,bs);CHKERRQ(ierr);
427565245c5SBarry Smith     }
428705e6b8bSstefano_zampini   }
42969ce434fSBarry Smith   map->bs = bs;
43069ce434fSBarry Smith   PetscFunctionReturn(0);
43169ce434fSBarry Smith }
43269ce434fSBarry Smith 
433c3002683SMatthew G. Knepley /*@
43469ce434fSBarry Smith   PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object.
43569ce434fSBarry Smith 
43669ce434fSBarry Smith   Not Collective
43769ce434fSBarry Smith 
43869ce434fSBarry Smith   Input Parameters:
43969ce434fSBarry Smith . map - pointer to the map
44069ce434fSBarry Smith 
44169ce434fSBarry Smith   Output Parameters:
44269ce434fSBarry Smith . bs - the size
44369ce434fSBarry Smith 
44469ce434fSBarry Smith   Level: developer
44569ce434fSBarry Smith 
44669ce434fSBarry Smith   Notes:
44769ce434fSBarry Smith   Call this after the call to PetscLayoutSetUp()
44869ce434fSBarry Smith 
44969ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
45069ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize()
45169ce434fSBarry Smith @*/
45269ce434fSBarry Smith PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs)
45369ce434fSBarry Smith {
45469ce434fSBarry Smith   PetscFunctionBegin;
45533d57670SJed Brown   *bs = PetscAbs(map->bs);
45669ce434fSBarry Smith   PetscFunctionReturn(0);
45769ce434fSBarry Smith }
45869ce434fSBarry Smith 
459c3002683SMatthew G. Knepley /*@
46069ce434fSBarry Smith   PetscLayoutGetRange - gets the range of values owned by this process
46169ce434fSBarry Smith 
46269ce434fSBarry Smith   Not Collective
46369ce434fSBarry Smith 
46469ce434fSBarry Smith   Input Parameters:
46569ce434fSBarry Smith . map - pointer to the map
46669ce434fSBarry Smith 
46769ce434fSBarry Smith   Output Parameters:
46869ce434fSBarry Smith + rstart - first index owned by this process
46969ce434fSBarry Smith - rend   - one more than the last index owned by this process
47069ce434fSBarry Smith 
47169ce434fSBarry Smith   Level: developer
47269ce434fSBarry Smith 
47369ce434fSBarry Smith   Notes:
47469ce434fSBarry Smith   Call this after the call to PetscLayoutSetUp()
47569ce434fSBarry Smith 
47669ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
47769ce434fSBarry Smith           PetscLayoutGetSize(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
47869ce434fSBarry Smith @*/
47969ce434fSBarry Smith PetscErrorCode PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend)
48069ce434fSBarry Smith {
48169ce434fSBarry Smith   PetscFunctionBegin;
48269ce434fSBarry Smith   if (rstart) *rstart = map->rstart;
48369ce434fSBarry Smith   if (rend)   *rend   = map->rend;
48469ce434fSBarry Smith   PetscFunctionReturn(0);
48569ce434fSBarry Smith }
48669ce434fSBarry Smith 
48769ce434fSBarry Smith /*@C
48869ce434fSBarry Smith      PetscLayoutGetRanges - gets the range of values owned by all processes
48969ce434fSBarry Smith 
49069ce434fSBarry Smith     Not Collective
49169ce434fSBarry Smith 
49269ce434fSBarry Smith    Input Parameters:
49369ce434fSBarry Smith .    map - pointer to the map
49469ce434fSBarry Smith 
49569ce434fSBarry Smith    Output Parameters:
49669ce434fSBarry Smith .    range - start of each processors range of indices (the final entry is one more then the
49769ce434fSBarry Smith              last index on the last process)
49869ce434fSBarry Smith 
49969ce434fSBarry Smith    Level: developer
50069ce434fSBarry Smith 
50169ce434fSBarry Smith     Notes:
50269ce434fSBarry Smith        Call this after the call to PetscLayoutSetUp()
50369ce434fSBarry Smith 
50469ce434fSBarry Smith     Fortran Notes:
50569ce434fSBarry Smith       Not available from Fortran
50669ce434fSBarry Smith 
50769ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
50869ce434fSBarry Smith           PetscLayoutGetSize(), PetscLayoutGetRange(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
50969ce434fSBarry Smith 
51069ce434fSBarry Smith @*/
51169ce434fSBarry Smith PetscErrorCode  PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[])
51269ce434fSBarry Smith {
51369ce434fSBarry Smith   PetscFunctionBegin;
51469ce434fSBarry Smith   *range = map->range;
51569ce434fSBarry Smith   PetscFunctionReturn(0);
51669ce434fSBarry Smith }
51769ce434fSBarry Smith 
51869ce434fSBarry Smith /*@C
51969ce434fSBarry Smith    PetscSFSetGraphLayout - Set a parallel star forest via global indices and a PetscLayout
52069ce434fSBarry Smith 
52169ce434fSBarry Smith    Collective
52269ce434fSBarry Smith 
52369ce434fSBarry Smith    Input Arguments:
52469ce434fSBarry Smith +  sf - star forest
52569ce434fSBarry Smith .  layout - PetscLayout defining the global space
52669ce434fSBarry Smith .  nleaves - number of leaf vertices on the current process, each of these references a root on any process
52769ce434fSBarry Smith .  ilocal - locations of leaves in leafdata buffers, pass NULL for contiguous storage
528cf79137fSStefano Zampini .  localmode - copy mode for ilocal
52969ce434fSBarry Smith -  iremote - remote locations of root vertices for each leaf on the current process
53069ce434fSBarry Smith 
53169ce434fSBarry Smith    Level: intermediate
53269ce434fSBarry Smith 
533cf79137fSStefano Zampini    Developers Note: Local indices which are the identity permutation in the range [0,nleaves) are discarded as they
534cf79137fSStefano Zampini    encode contiguous storage. In such case, if localmode is PETSC_OWN_POINTER, the memory is deallocated as it is not
535cf79137fSStefano Zampini    needed
536cf79137fSStefano Zampini 
53769ce434fSBarry Smith .seealso: PetscSFCreate(), PetscSFView(), PetscSFSetGraph(), PetscSFGetGraph()
53869ce434fSBarry Smith @*/
53969ce434fSBarry Smith PetscErrorCode PetscSFSetGraphLayout(PetscSF sf,PetscLayout layout,PetscInt nleaves,const PetscInt *ilocal,PetscCopyMode localmode,const PetscInt *iremote)
54069ce434fSBarry Smith {
54169ce434fSBarry Smith   PetscErrorCode ierr;
54269ce434fSBarry Smith   PetscInt       i,nroots;
54369ce434fSBarry Smith   PetscSFNode    *remote;
54469ce434fSBarry Smith 
54569ce434fSBarry Smith   PetscFunctionBegin;
54669ce434fSBarry Smith   ierr = PetscLayoutGetLocalSize(layout,&nroots);CHKERRQ(ierr);
547785e854fSJed Brown   ierr = PetscMalloc1(nleaves,&remote);CHKERRQ(ierr);
54869ce434fSBarry Smith   for (i=0; i<nleaves; i++) {
54969ce434fSBarry Smith     PetscInt owner = -1;
55069ce434fSBarry Smith     ierr = PetscLayoutFindOwner(layout,iremote[i],&owner);CHKERRQ(ierr);
55169ce434fSBarry Smith     remote[i].rank  = owner;
55269ce434fSBarry Smith     remote[i].index = iremote[i] - layout->range[owner];
55369ce434fSBarry Smith   }
55469ce434fSBarry Smith   ierr = PetscSFSetGraph(sf,nroots,nleaves,ilocal,localmode,remote,PETSC_OWN_POINTER);CHKERRQ(ierr);
55569ce434fSBarry Smith   PetscFunctionReturn(0);
55669ce434fSBarry Smith }
55769ce434fSBarry Smith 
558f92d6284SStefano Zampini /*@
559f92d6284SStefano Zampini   PetscLayoutCompare - Compares two layouts
560f92d6284SStefano Zampini 
561f92d6284SStefano Zampini   Not Collective
562f92d6284SStefano Zampini 
563f92d6284SStefano Zampini   Input Parameters:
564d11c674dSStefano Zampini + mapa - pointer to the first map
565f92d6284SStefano Zampini - mapb - pointer to the second map
566f92d6284SStefano Zampini 
567f92d6284SStefano Zampini   Output Parameters:
568f92d6284SStefano Zampini . congruent - PETSC_TRUE if the two layouts are congruent, PETSC_FALSE otherwise
569f92d6284SStefano Zampini 
570f92d6284SStefano Zampini   Level: beginner
571f92d6284SStefano Zampini 
572f92d6284SStefano Zampini   Notes:
573f92d6284SStefano Zampini 
574f92d6284SStefano Zampini .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
575f92d6284SStefano Zampini           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
576f92d6284SStefano Zampini @*/
577f92d6284SStefano Zampini PetscErrorCode PetscLayoutCompare(PetscLayout mapa,PetscLayout mapb,PetscBool *congruent)
578f92d6284SStefano Zampini {
579f92d6284SStefano Zampini   PetscErrorCode ierr;
580f92d6284SStefano Zampini   PetscMPIInt    sizea,sizeb;
581f92d6284SStefano Zampini 
582f92d6284SStefano Zampini   PetscFunctionBegin;
583f92d6284SStefano Zampini   *congruent = PETSC_FALSE;
584f92d6284SStefano Zampini   ierr = MPI_Comm_size(mapa->comm,&sizea);CHKERRQ(ierr);
585f92d6284SStefano Zampini   ierr = MPI_Comm_size(mapb->comm,&sizeb);CHKERRQ(ierr);
586f92d6284SStefano Zampini   if (mapa->N == mapb->N && mapa->range && mapb->range && sizea == sizeb) {
587580bdb30SBarry Smith     ierr = PetscArraycmp(mapa->range,mapb->range,sizea+1,congruent);CHKERRQ(ierr);
588f92d6284SStefano Zampini   }
589f92d6284SStefano Zampini   PetscFunctionReturn(0);
590f92d6284SStefano Zampini }
591a72d46e8SStefano Zampini 
592a72d46e8SStefano Zampini /* TODO: handle nooffprocentries like MatZeroRowsMapLocal_Private, since this code is the same */
593a72d46e8SStefano Zampini PetscErrorCode PetscLayoutMapLocal(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
594a72d46e8SStefano Zampini {
595a72d46e8SStefano Zampini   PetscInt      *owners = map->range;
596a72d46e8SStefano Zampini   PetscInt       n      = map->n;
597a72d46e8SStefano Zampini   PetscSF        sf;
598a72d46e8SStefano Zampini   PetscInt      *lidxs,*work = NULL;
599a72d46e8SStefano Zampini   PetscSFNode   *ridxs;
600a72d46e8SStefano Zampini   PetscMPIInt    rank;
601a72d46e8SStefano Zampini   PetscInt       r, p = 0, len = 0;
602a72d46e8SStefano Zampini   PetscErrorCode ierr;
603a72d46e8SStefano Zampini 
604a72d46e8SStefano Zampini   PetscFunctionBegin;
605a72d46e8SStefano Zampini   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
606a72d46e8SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs */
607a72d46e8SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
608a72d46e8SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
609a72d46e8SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
610a72d46e8SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
611a72d46e8SStefano Zampini   for (r = 0; r < N; ++r) {
612a72d46e8SStefano Zampini     const PetscInt idx = idxs[r];
613a72d46e8SStefano 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);
614a72d46e8SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
615a72d46e8SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
616a72d46e8SStefano Zampini     }
617a72d46e8SStefano Zampini     ridxs[r].rank = p;
618a72d46e8SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
619a72d46e8SStefano Zampini   }
620a72d46e8SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
621a72d46e8SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
622a72d46e8SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
623a72d46e8SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
624a72d46e8SStefano Zampini   if (ogidxs) { /* communicate global idxs */
625a72d46e8SStefano Zampini     PetscInt cum = 0,start,*work2;
626a72d46e8SStefano Zampini 
627a72d46e8SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
628a72d46e8SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
629a72d46e8SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
630a72d46e8SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
631a72d46e8SStefano Zampini     start -= cum;
632a72d46e8SStefano Zampini     cum = 0;
633a72d46e8SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
634a72d46e8SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
635a72d46e8SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
636a72d46e8SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
637a72d46e8SStefano Zampini   }
638a72d46e8SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
639a72d46e8SStefano Zampini   /* Compress and put in indices */
640a72d46e8SStefano Zampini   for (r = 0; r < n; ++r)
641a72d46e8SStefano Zampini     if (lidxs[r] >= 0) {
642a72d46e8SStefano Zampini       if (work) work[len] = work[r];
643a72d46e8SStefano Zampini       lidxs[len++] = r;
644a72d46e8SStefano Zampini     }
645a72d46e8SStefano Zampini   if (on) *on = len;
646a72d46e8SStefano Zampini   if (oidxs) *oidxs = lidxs;
647a72d46e8SStefano Zampini   if (ogidxs) *ogidxs = work;
648a72d46e8SStefano Zampini   PetscFunctionReturn(0);
649a72d46e8SStefano Zampini }
650