xref: /petsc/src/vec/is/utils/pmap.c (revision 07acc2aeea7a273014b10cda4fb272aa3ba8a1b1)
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>
8*07acc2aeSBarry Smith #include <petsc/private/isimpl.h>
95c25fcd7SBarry Smith 
10c3002683SMatthew G. Knepley /*@
1169ce434fSBarry Smith   PetscLayoutCreate - Allocates PetscLayout space and sets the map contents to the default.
1269ce434fSBarry Smith 
1369ce434fSBarry Smith   Collective on MPI_Comm
1469ce434fSBarry Smith 
1569ce434fSBarry Smith   Input Parameters:
1669ce434fSBarry Smith + comm - the MPI communicator
1769ce434fSBarry Smith - map - pointer to the map
1869ce434fSBarry Smith 
19456fcb79SJed Brown   Level: advanced
2069ce434fSBarry Smith 
21456fcb79SJed Brown   Notes:
22456fcb79SJed Brown   Typical calling sequence
23456fcb79SJed Brown .vb
2469ce434fSBarry Smith        PetscLayoutCreate(MPI_Comm,PetscLayout *);
2569ce434fSBarry Smith        PetscLayoutSetBlockSize(PetscLayout,1);
26456fcb79SJed Brown        PetscLayoutSetSize(PetscLayout,N) // or PetscLayoutSetLocalSize(PetscLayout,n);
2769ce434fSBarry Smith        PetscLayoutSetUp(PetscLayout);
28456fcb79SJed Brown .ve
2969ce434fSBarry Smith   Optionally use any of the following:
30456fcb79SJed Brown 
31456fcb79SJed Brown + PetscLayoutGetSize(PetscLayout,PetscInt *);
32456fcb79SJed Brown . PetscLayoutGetLocalSize(PetscLayout,PetscInt *);
33456fcb79SJed Brown . PetscLayoutGetRange(PetscLayout,PetscInt *rstart,PetscInt *rend);
34456fcb79SJed Brown . PetscLayoutGetRanges(PetscLayout,const PetscInt *range[]);
35456fcb79SJed Brown - PetscLayoutDestroy(PetscLayout*);
3669ce434fSBarry Smith 
3769ce434fSBarry Smith   The PetscLayout object and methods are intended to be used in the PETSc Vec and Mat implementions; it is often not needed in
3869ce434fSBarry Smith   user codes unless you really gain something in their use.
3969ce434fSBarry Smith 
4069ce434fSBarry Smith .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
4169ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp()
4269ce434fSBarry Smith 
4369ce434fSBarry Smith @*/
4469ce434fSBarry Smith PetscErrorCode PetscLayoutCreate(MPI_Comm comm,PetscLayout *map)
4569ce434fSBarry Smith {
4669ce434fSBarry Smith   PetscErrorCode ierr;
4769ce434fSBarry Smith 
4869ce434fSBarry Smith   PetscFunctionBegin;
49b00a9115SJed Brown   ierr = PetscNew(map);CHKERRQ(ierr);
5069ce434fSBarry Smith 
5169ce434fSBarry Smith   (*map)->comm   = comm;
5269ce434fSBarry Smith   (*map)->bs     = -1;
5369ce434fSBarry Smith   (*map)->n      = -1;
5469ce434fSBarry Smith   (*map)->N      = -1;
55f92d6284SStefano Zampini   (*map)->range  = NULL;
5669ce434fSBarry Smith   (*map)->rstart = 0;
5769ce434fSBarry Smith   (*map)->rend   = 0;
5869ce434fSBarry Smith   PetscFunctionReturn(0);
5969ce434fSBarry Smith }
6069ce434fSBarry Smith 
61c3002683SMatthew G. Knepley /*@
6269ce434fSBarry Smith   PetscLayoutDestroy - Frees a map object and frees its range if that exists.
6369ce434fSBarry Smith 
6469ce434fSBarry Smith   Collective on MPI_Comm
6569ce434fSBarry Smith 
6669ce434fSBarry Smith   Input Parameters:
6769ce434fSBarry Smith . map - the PetscLayout
6869ce434fSBarry Smith 
6969ce434fSBarry Smith   Level: developer
7069ce434fSBarry Smith 
71c3002683SMatthew G. Knepley   Note:
7269ce434fSBarry Smith   The PetscLayout object and methods are intended to be used in the PETSc Vec and Mat implementions; it is
7369ce434fSBarry Smith   recommended they not be used in user codes unless you really gain something in their use.
7469ce434fSBarry Smith 
7569ce434fSBarry Smith .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutCreate(),
7669ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp()
7769ce434fSBarry Smith 
7869ce434fSBarry Smith @*/
7969ce434fSBarry Smith PetscErrorCode PetscLayoutDestroy(PetscLayout *map)
8069ce434fSBarry Smith {
8169ce434fSBarry Smith   PetscErrorCode ierr;
8269ce434fSBarry Smith 
8369ce434fSBarry Smith   PetscFunctionBegin;
8469ce434fSBarry Smith   if (!*map) PetscFunctionReturn(0);
8569ce434fSBarry Smith   if (!(*map)->refcnt--) {
8669ce434fSBarry Smith     ierr = PetscFree((*map)->range);CHKERRQ(ierr);
8769ce434fSBarry Smith     ierr = ISLocalToGlobalMappingDestroy(&(*map)->mapping);CHKERRQ(ierr);
8869ce434fSBarry Smith     ierr = PetscFree((*map));CHKERRQ(ierr);
8969ce434fSBarry Smith   }
9069ce434fSBarry Smith   *map = NULL;
9169ce434fSBarry Smith   PetscFunctionReturn(0);
9269ce434fSBarry Smith }
9369ce434fSBarry Smith 
947b659617SVaclav Hapla static PetscErrorCode PetscLayoutSetUp_SizesFromRanges_Private(PetscLayout map)
957b659617SVaclav Hapla {
967b659617SVaclav Hapla   PetscMPIInt    rank,size;
977b659617SVaclav Hapla   PetscErrorCode ierr;
987b659617SVaclav Hapla 
997b659617SVaclav Hapla   PetscFunctionBegin;
1007b659617SVaclav Hapla   ierr = MPI_Comm_size(map->comm, &size);CHKERRQ(ierr);
1017b659617SVaclav Hapla   ierr = MPI_Comm_rank(map->comm, &rank);CHKERRQ(ierr);
1027b659617SVaclav Hapla   map->rstart = map->range[rank];
1037b659617SVaclav Hapla   map->rend   = map->range[rank+1];
1047b659617SVaclav Hapla   map->n      = map->rend - map->rstart;
1057b659617SVaclav Hapla   map->N      = map->range[size];
1067b659617SVaclav Hapla #if defined(PETSC_USE_DEBUG)
1077b659617SVaclav Hapla   /* just check that n, N and bs are consistent */
1087b659617SVaclav Hapla   {
1097b659617SVaclav Hapla     PetscInt tmp;
1107b659617SVaclav Hapla     ierr = MPIU_Allreduce(&map->n,&tmp,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
1117b659617SVaclav 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);
1127b659617SVaclav Hapla   }
1137b659617SVaclav Hapla   if (map->bs > 1) {
1147b659617SVaclav 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);
1157b659617SVaclav Hapla   }
1167b659617SVaclav Hapla   if (map->bs > 1) {
1177b659617SVaclav 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);
1187b659617SVaclav Hapla   }
1197b659617SVaclav Hapla #endif
1207b659617SVaclav Hapla   PetscFunctionReturn(0);
1217b659617SVaclav Hapla }
1227b659617SVaclav Hapla 
123c3002683SMatthew G. Knepley /*@
12469ce434fSBarry Smith   PetscLayoutSetUp - given a map where you have set either the global or local
12569ce434fSBarry Smith                      size sets up the map so that it may be used.
12669ce434fSBarry Smith 
12769ce434fSBarry Smith   Collective on MPI_Comm
12869ce434fSBarry Smith 
12969ce434fSBarry Smith   Input Parameters:
13069ce434fSBarry Smith . map - pointer to the map
13169ce434fSBarry Smith 
13269ce434fSBarry Smith   Level: developer
13369ce434fSBarry Smith 
13495452b02SPatrick Sanan   Notes:
13595452b02SPatrick Sanan     Typical calling sequence
136c3002683SMatthew G. Knepley $ PetscLayoutCreate(MPI_Comm,PetscLayout *);
137c3002683SMatthew G. Knepley $ PetscLayoutSetBlockSize(PetscLayout,1);
138c3002683SMatthew G. Knepley $ PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both
139c3002683SMatthew G. Knepley $ PetscLayoutSetUp(PetscLayout);
140c3002683SMatthew G. Knepley $ PetscLayoutGetSize(PetscLayout,PetscInt *);
14169ce434fSBarry Smith 
1427b659617SVaclav Hapla   If range exists, and local size is not set, everything gets computed from the range.
14369ce434fSBarry Smith 
14469ce434fSBarry Smith   If the local size, global size are already set and range exists then this does nothing.
14569ce434fSBarry Smith 
14669ce434fSBarry Smith .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
14769ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutCreate()
14869ce434fSBarry Smith @*/
14969ce434fSBarry Smith PetscErrorCode PetscLayoutSetUp(PetscLayout map)
15069ce434fSBarry Smith {
15169ce434fSBarry Smith   PetscMPIInt    rank,size;
15269ce434fSBarry Smith   PetscInt       p;
15369ce434fSBarry Smith   PetscErrorCode ierr;
15469ce434fSBarry Smith 
15569ce434fSBarry Smith   PetscFunctionBegin;
15669ce434fSBarry Smith   if ((map->n >= 0) && (map->N >= 0) && (map->range)) PetscFunctionReturn(0);
1577b659617SVaclav Hapla   if (map->range && map->n < 0) {
1587b659617SVaclav Hapla     ierr = PetscLayoutSetUp_SizesFromRanges_Private(map);CHKERRQ(ierr);
1597b659617SVaclav Hapla     PetscFunctionReturn(0);
1607b659617SVaclav Hapla   }
16169ce434fSBarry Smith 
162b146b01cSBarry Smith   if (map->n > 0 && map->bs > 1) {
163ec4d677dSStefano 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);
164b146b01cSBarry Smith   }
165b146b01cSBarry Smith   if (map->N > 0 && map->bs > 1) {
166ec4d677dSStefano 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);
167b146b01cSBarry Smith   }
168b146b01cSBarry Smith 
16969ce434fSBarry Smith   ierr = MPI_Comm_size(map->comm, &size);CHKERRQ(ierr);
17069ce434fSBarry Smith   ierr = MPI_Comm_rank(map->comm, &rank);CHKERRQ(ierr);
17133d57670SJed Brown   if (map->n > 0) map->n = map->n/PetscAbs(map->bs);
17233d57670SJed Brown   if (map->N > 0) map->N = map->N/PetscAbs(map->bs);
17369ce434fSBarry Smith   ierr = PetscSplitOwnership(map->comm,&map->n,&map->N);CHKERRQ(ierr);
17433d57670SJed Brown   map->n = map->n*PetscAbs(map->bs);
17533d57670SJed Brown   map->N = map->N*PetscAbs(map->bs);
17669ce434fSBarry Smith   if (!map->range) {
177854ce69bSBarry Smith     ierr = PetscMalloc1(size+1, &map->range);CHKERRQ(ierr);
17869ce434fSBarry Smith   }
17969ce434fSBarry Smith   ierr = MPI_Allgather(&map->n, 1, MPIU_INT, map->range+1, 1, MPIU_INT, map->comm);CHKERRQ(ierr);
18069ce434fSBarry Smith 
18169ce434fSBarry Smith   map->range[0] = 0;
18269ce434fSBarry Smith   for (p = 2; p <= size; p++) map->range[p] += map->range[p-1];
18369ce434fSBarry Smith 
18469ce434fSBarry Smith   map->rstart = map->range[rank];
18569ce434fSBarry Smith   map->rend   = map->range[rank+1];
18669ce434fSBarry Smith   PetscFunctionReturn(0);
18769ce434fSBarry Smith }
18869ce434fSBarry Smith 
189c3002683SMatthew G. Knepley /*@
19069ce434fSBarry Smith   PetscLayoutDuplicate - creates a new PetscLayout with the same information as a given one. If the PetscLayout already exists it is destroyed first.
19169ce434fSBarry Smith 
19269ce434fSBarry Smith   Collective on PetscLayout
19369ce434fSBarry Smith 
19469ce434fSBarry Smith   Input Parameter:
19569ce434fSBarry Smith . in - input PetscLayout to be duplicated
19669ce434fSBarry Smith 
19769ce434fSBarry Smith   Output Parameter:
19869ce434fSBarry Smith . out - the copy
19969ce434fSBarry Smith 
20069ce434fSBarry Smith   Level: developer
20169ce434fSBarry Smith 
20295452b02SPatrick Sanan   Notes:
20395452b02SPatrick Sanan     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
20469ce434fSBarry Smith 
20569ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutReference()
20669ce434fSBarry Smith @*/
20769ce434fSBarry Smith PetscErrorCode PetscLayoutDuplicate(PetscLayout in,PetscLayout *out)
20869ce434fSBarry Smith {
20969ce434fSBarry Smith   PetscMPIInt    size;
21069ce434fSBarry Smith   PetscErrorCode ierr;
21169ce434fSBarry Smith   MPI_Comm       comm = in->comm;
21269ce434fSBarry Smith 
21369ce434fSBarry Smith   PetscFunctionBegin;
21469ce434fSBarry Smith   ierr = PetscLayoutDestroy(out);CHKERRQ(ierr);
21569ce434fSBarry Smith   ierr = PetscLayoutCreate(comm,out);CHKERRQ(ierr);
21669ce434fSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
21769ce434fSBarry Smith   ierr = PetscMemcpy(*out,in,sizeof(struct _n_PetscLayout));CHKERRQ(ierr);
218854ce69bSBarry Smith   ierr = PetscMalloc1(size+1,&(*out)->range);CHKERRQ(ierr);
21969ce434fSBarry Smith   ierr = PetscMemcpy((*out)->range,in->range,(size+1)*sizeof(PetscInt));CHKERRQ(ierr);
22069ce434fSBarry Smith 
22169ce434fSBarry Smith   (*out)->refcnt = 0;
22269ce434fSBarry Smith   PetscFunctionReturn(0);
22369ce434fSBarry Smith }
22469ce434fSBarry Smith 
225c3002683SMatthew G. Knepley /*@
22669ce434fSBarry Smith   PetscLayoutReference - Causes a PETSc Vec or Mat to share a PetscLayout with one that already exists. Used by Vec/MatDuplicate_XXX()
22769ce434fSBarry Smith 
22869ce434fSBarry Smith   Collective on PetscLayout
22969ce434fSBarry Smith 
23069ce434fSBarry Smith   Input Parameter:
23169ce434fSBarry Smith . in - input PetscLayout to be copied
23269ce434fSBarry Smith 
23369ce434fSBarry Smith   Output Parameter:
23469ce434fSBarry Smith . out - the reference location
23569ce434fSBarry Smith 
23669ce434fSBarry Smith   Level: developer
23769ce434fSBarry Smith 
23895452b02SPatrick Sanan   Notes:
23995452b02SPatrick Sanan     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
24069ce434fSBarry Smith 
24169ce434fSBarry Smith   If the out location already contains a PetscLayout it is destroyed
24269ce434fSBarry Smith 
24369ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
24469ce434fSBarry Smith @*/
24569ce434fSBarry Smith PetscErrorCode PetscLayoutReference(PetscLayout in,PetscLayout *out)
24669ce434fSBarry Smith {
24769ce434fSBarry Smith   PetscErrorCode ierr;
24869ce434fSBarry Smith 
24969ce434fSBarry Smith   PetscFunctionBegin;
25069ce434fSBarry Smith   in->refcnt++;
25169ce434fSBarry Smith   ierr = PetscLayoutDestroy(out);CHKERRQ(ierr);
25269ce434fSBarry Smith   *out = in;
25369ce434fSBarry Smith   PetscFunctionReturn(0);
25469ce434fSBarry Smith }
25569ce434fSBarry Smith 
256c3002683SMatthew G. Knepley /*@
25769ce434fSBarry Smith   PetscLayoutSetISLocalToGlobalMapping - sets a ISLocalGlobalMapping into a PetscLayout
25869ce434fSBarry Smith 
25969ce434fSBarry Smith   Collective on PetscLayout
26069ce434fSBarry Smith 
26169ce434fSBarry Smith   Input Parameter:
26269ce434fSBarry Smith + in - input PetscLayout
26369ce434fSBarry Smith - ltog - the local to global mapping
26469ce434fSBarry Smith 
26569ce434fSBarry Smith 
26669ce434fSBarry Smith   Level: developer
26769ce434fSBarry Smith 
26895452b02SPatrick Sanan   Notes:
26995452b02SPatrick Sanan     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
27069ce434fSBarry Smith 
27169ce434fSBarry Smith   If the ltog location already contains a PetscLayout it is destroyed
27269ce434fSBarry Smith 
273a188d78dSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
27469ce434fSBarry Smith @*/
27569ce434fSBarry Smith PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in,ISLocalToGlobalMapping ltog)
27669ce434fSBarry Smith {
27769ce434fSBarry Smith   PetscErrorCode ierr;
27845b6f7e9SBarry Smith   PetscInt       bs;
27969ce434fSBarry Smith 
28069ce434fSBarry Smith   PetscFunctionBegin;
28145b6f7e9SBarry Smith   ierr = ISLocalToGlobalMappingGetBlockSize(ltog,&bs);CHKERRQ(ierr);
28237461477SLawrence 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);
28369ce434fSBarry Smith   ierr = PetscObjectReference((PetscObject)ltog);CHKERRQ(ierr);
28469ce434fSBarry Smith   ierr = ISLocalToGlobalMappingDestroy(&in->mapping);CHKERRQ(ierr);
28569ce434fSBarry Smith   in->mapping = ltog;
28669ce434fSBarry Smith   PetscFunctionReturn(0);
28769ce434fSBarry Smith }
28869ce434fSBarry Smith 
289c3002683SMatthew G. Knepley /*@
29069ce434fSBarry Smith   PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object.
29169ce434fSBarry Smith 
29269ce434fSBarry Smith   Collective on PetscLayout
29369ce434fSBarry Smith 
29469ce434fSBarry Smith   Input Parameters:
29569ce434fSBarry Smith + map - pointer to the map
29669ce434fSBarry Smith - n - the local size
29769ce434fSBarry Smith 
29869ce434fSBarry Smith   Level: developer
29969ce434fSBarry Smith 
30069ce434fSBarry Smith   Notes:
30169ce434fSBarry Smith   Call this after the call to PetscLayoutCreate()
30269ce434fSBarry Smith 
30369ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
30469ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
30569ce434fSBarry Smith @*/
30669ce434fSBarry Smith PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map,PetscInt n)
30769ce434fSBarry Smith {
30869ce434fSBarry Smith   PetscFunctionBegin;
30969ce434fSBarry 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);
31069ce434fSBarry Smith   map->n = n;
31169ce434fSBarry Smith   PetscFunctionReturn(0);
31269ce434fSBarry Smith }
31369ce434fSBarry Smith 
31469ce434fSBarry Smith /*@C
31569ce434fSBarry Smith      PetscLayoutGetLocalSize - Gets the local size for a PetscLayout object.
31669ce434fSBarry Smith 
31769ce434fSBarry Smith     Not Collective
31869ce434fSBarry Smith 
31969ce434fSBarry Smith    Input Parameters:
32069ce434fSBarry Smith .    map - pointer to the map
32169ce434fSBarry Smith 
32269ce434fSBarry Smith    Output Parameters:
32369ce434fSBarry Smith .    n - the local size
32469ce434fSBarry Smith 
32569ce434fSBarry Smith    Level: developer
32669ce434fSBarry Smith 
32769ce434fSBarry Smith     Notes:
32869ce434fSBarry Smith        Call this after the call to PetscLayoutSetUp()
32969ce434fSBarry Smith 
33069ce434fSBarry Smith     Fortran Notes:
33169ce434fSBarry Smith       Not available from Fortran
33269ce434fSBarry Smith 
33369ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
33469ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
33569ce434fSBarry Smith 
33669ce434fSBarry Smith @*/
33769ce434fSBarry Smith PetscErrorCode  PetscLayoutGetLocalSize(PetscLayout map,PetscInt *n)
33869ce434fSBarry Smith {
33969ce434fSBarry Smith   PetscFunctionBegin;
34069ce434fSBarry Smith   *n = map->n;
34169ce434fSBarry Smith   PetscFunctionReturn(0);
34269ce434fSBarry Smith }
34369ce434fSBarry Smith 
344c3002683SMatthew G. Knepley /*@
34569ce434fSBarry Smith   PetscLayoutSetSize - Sets the global size for a PetscLayout object.
34669ce434fSBarry Smith 
34769ce434fSBarry Smith   Logically Collective on PetscLayout
34869ce434fSBarry Smith 
34969ce434fSBarry Smith   Input Parameters:
35069ce434fSBarry Smith + map - pointer to the map
35169ce434fSBarry Smith - n - the global size
35269ce434fSBarry Smith 
35369ce434fSBarry Smith   Level: developer
35469ce434fSBarry Smith 
35569ce434fSBarry Smith   Notes:
35669ce434fSBarry Smith   Call this after the call to PetscLayoutCreate()
35769ce434fSBarry Smith 
35869ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
35969ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
36069ce434fSBarry Smith @*/
36169ce434fSBarry Smith PetscErrorCode PetscLayoutSetSize(PetscLayout map,PetscInt n)
36269ce434fSBarry Smith {
36369ce434fSBarry Smith   PetscFunctionBegin;
36469ce434fSBarry Smith   map->N = n;
36569ce434fSBarry Smith   PetscFunctionReturn(0);
36669ce434fSBarry Smith }
36769ce434fSBarry Smith 
368c3002683SMatthew G. Knepley /*@
36969ce434fSBarry Smith   PetscLayoutGetSize - Gets the global size for a PetscLayout object.
37069ce434fSBarry Smith 
37169ce434fSBarry Smith   Not Collective
37269ce434fSBarry Smith 
37369ce434fSBarry Smith   Input Parameters:
37469ce434fSBarry Smith . map - pointer to the map
37569ce434fSBarry Smith 
37669ce434fSBarry Smith   Output Parameters:
37769ce434fSBarry Smith . n - the global size
37869ce434fSBarry Smith 
37969ce434fSBarry Smith   Level: developer
38069ce434fSBarry Smith 
38169ce434fSBarry Smith   Notes:
38269ce434fSBarry Smith   Call this after the call to PetscLayoutSetUp()
38369ce434fSBarry Smith 
38469ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
38569ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
38669ce434fSBarry Smith @*/
38769ce434fSBarry Smith PetscErrorCode PetscLayoutGetSize(PetscLayout map,PetscInt *n)
38869ce434fSBarry Smith {
38969ce434fSBarry Smith   PetscFunctionBegin;
39069ce434fSBarry Smith   *n = map->N;
39169ce434fSBarry Smith   PetscFunctionReturn(0);
39269ce434fSBarry Smith }
39369ce434fSBarry Smith 
394c3002683SMatthew G. Knepley /*@
39569ce434fSBarry Smith   PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object.
39669ce434fSBarry Smith 
39769ce434fSBarry Smith   Logically Collective on PetscLayout
39869ce434fSBarry Smith 
39969ce434fSBarry Smith   Input Parameters:
40069ce434fSBarry Smith + map - pointer to the map
40169ce434fSBarry Smith - bs - the size
40269ce434fSBarry Smith 
40369ce434fSBarry Smith   Level: developer
40469ce434fSBarry Smith 
40569ce434fSBarry Smith   Notes:
40669ce434fSBarry Smith   Call this after the call to PetscLayoutCreate()
40769ce434fSBarry Smith 
40869ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
40969ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
41069ce434fSBarry Smith @*/
41169ce434fSBarry Smith PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs)
41269ce434fSBarry Smith {
41369ce434fSBarry Smith   PetscFunctionBegin;
41469bbac97SJed Brown   if (bs < 0) PetscFunctionReturn(0);
415299e779cSStefano 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);
416565245c5SBarry Smith   if (map->mapping) {
417705e6b8bSstefano_zampini     PetscInt       obs;
418565245c5SBarry Smith     PetscErrorCode ierr;
419565245c5SBarry Smith 
420705e6b8bSstefano_zampini     ierr = ISLocalToGlobalMappingGetBlockSize(map->mapping,&obs);CHKERRQ(ierr);
421705e6b8bSstefano_zampini     if (obs > 1) {
42263fa5c83Sstefano_zampini       ierr = ISLocalToGlobalMappingSetBlockSize(map->mapping,bs);CHKERRQ(ierr);
423565245c5SBarry Smith     }
424705e6b8bSstefano_zampini   }
42569ce434fSBarry Smith   map->bs = bs;
42669ce434fSBarry Smith   PetscFunctionReturn(0);
42769ce434fSBarry Smith }
42869ce434fSBarry Smith 
429c3002683SMatthew G. Knepley /*@
43069ce434fSBarry Smith   PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object.
43169ce434fSBarry Smith 
43269ce434fSBarry Smith   Not Collective
43369ce434fSBarry Smith 
43469ce434fSBarry Smith   Input Parameters:
43569ce434fSBarry Smith . map - pointer to the map
43669ce434fSBarry Smith 
43769ce434fSBarry Smith   Output Parameters:
43869ce434fSBarry Smith . bs - the size
43969ce434fSBarry Smith 
44069ce434fSBarry Smith   Level: developer
44169ce434fSBarry Smith 
44269ce434fSBarry Smith   Notes:
44369ce434fSBarry Smith   Call this after the call to PetscLayoutSetUp()
44469ce434fSBarry Smith 
44569ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
44669ce434fSBarry Smith           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize()
44769ce434fSBarry Smith @*/
44869ce434fSBarry Smith PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs)
44969ce434fSBarry Smith {
45069ce434fSBarry Smith   PetscFunctionBegin;
45133d57670SJed Brown   *bs = PetscAbs(map->bs);
45269ce434fSBarry Smith   PetscFunctionReturn(0);
45369ce434fSBarry Smith }
45469ce434fSBarry Smith 
455c3002683SMatthew G. Knepley /*@
45669ce434fSBarry Smith   PetscLayoutGetRange - gets the range of values owned by this process
45769ce434fSBarry Smith 
45869ce434fSBarry Smith   Not Collective
45969ce434fSBarry Smith 
46069ce434fSBarry Smith   Input Parameters:
46169ce434fSBarry Smith . map - pointer to the map
46269ce434fSBarry Smith 
46369ce434fSBarry Smith   Output Parameters:
46469ce434fSBarry Smith + rstart - first index owned by this process
46569ce434fSBarry Smith - rend   - one more than the last index owned by this process
46669ce434fSBarry Smith 
46769ce434fSBarry Smith   Level: developer
46869ce434fSBarry Smith 
46969ce434fSBarry Smith   Notes:
47069ce434fSBarry Smith   Call this after the call to PetscLayoutSetUp()
47169ce434fSBarry Smith 
47269ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
47369ce434fSBarry Smith           PetscLayoutGetSize(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
47469ce434fSBarry Smith @*/
47569ce434fSBarry Smith PetscErrorCode PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend)
47669ce434fSBarry Smith {
47769ce434fSBarry Smith   PetscFunctionBegin;
47869ce434fSBarry Smith   if (rstart) *rstart = map->rstart;
47969ce434fSBarry Smith   if (rend)   *rend   = map->rend;
48069ce434fSBarry Smith   PetscFunctionReturn(0);
48169ce434fSBarry Smith }
48269ce434fSBarry Smith 
48369ce434fSBarry Smith /*@C
48469ce434fSBarry Smith      PetscLayoutGetRanges - gets the range of values owned by all processes
48569ce434fSBarry Smith 
48669ce434fSBarry Smith     Not Collective
48769ce434fSBarry Smith 
48869ce434fSBarry Smith    Input Parameters:
48969ce434fSBarry Smith .    map - pointer to the map
49069ce434fSBarry Smith 
49169ce434fSBarry Smith    Output Parameters:
49269ce434fSBarry Smith .    range - start of each processors range of indices (the final entry is one more then the
49369ce434fSBarry Smith              last index on the last process)
49469ce434fSBarry Smith 
49569ce434fSBarry Smith    Level: developer
49669ce434fSBarry Smith 
49769ce434fSBarry Smith     Notes:
49869ce434fSBarry Smith        Call this after the call to PetscLayoutSetUp()
49969ce434fSBarry Smith 
50069ce434fSBarry Smith     Fortran Notes:
50169ce434fSBarry Smith       Not available from Fortran
50269ce434fSBarry Smith 
50369ce434fSBarry Smith .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
50469ce434fSBarry Smith           PetscLayoutGetSize(), PetscLayoutGetRange(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
50569ce434fSBarry Smith 
50669ce434fSBarry Smith @*/
50769ce434fSBarry Smith PetscErrorCode  PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[])
50869ce434fSBarry Smith {
50969ce434fSBarry Smith   PetscFunctionBegin;
51069ce434fSBarry Smith   *range = map->range;
51169ce434fSBarry Smith   PetscFunctionReturn(0);
51269ce434fSBarry Smith }
51369ce434fSBarry Smith 
51469ce434fSBarry Smith /*@C
51569ce434fSBarry Smith    PetscSFSetGraphLayout - Set a parallel star forest via global indices and a PetscLayout
51669ce434fSBarry Smith 
51769ce434fSBarry Smith    Collective
51869ce434fSBarry Smith 
51969ce434fSBarry Smith    Input Arguments:
52069ce434fSBarry Smith +  sf - star forest
52169ce434fSBarry Smith .  layout - PetscLayout defining the global space
52269ce434fSBarry Smith .  nleaves - number of leaf vertices on the current process, each of these references a root on any process
52369ce434fSBarry Smith .  ilocal - locations of leaves in leafdata buffers, pass NULL for contiguous storage
524cf79137fSStefano Zampini .  localmode - copy mode for ilocal
52569ce434fSBarry Smith -  iremote - remote locations of root vertices for each leaf on the current process
52669ce434fSBarry Smith 
52769ce434fSBarry Smith    Level: intermediate
52869ce434fSBarry Smith 
529cf79137fSStefano Zampini    Developers Note: Local indices which are the identity permutation in the range [0,nleaves) are discarded as they
530cf79137fSStefano Zampini    encode contiguous storage. In such case, if localmode is PETSC_OWN_POINTER, the memory is deallocated as it is not
531cf79137fSStefano Zampini    needed
532cf79137fSStefano Zampini 
53369ce434fSBarry Smith .seealso: PetscSFCreate(), PetscSFView(), PetscSFSetGraph(), PetscSFGetGraph()
53469ce434fSBarry Smith @*/
53569ce434fSBarry Smith PetscErrorCode PetscSFSetGraphLayout(PetscSF sf,PetscLayout layout,PetscInt nleaves,const PetscInt *ilocal,PetscCopyMode localmode,const PetscInt *iremote)
53669ce434fSBarry Smith {
53769ce434fSBarry Smith   PetscErrorCode ierr;
53869ce434fSBarry Smith   PetscInt       i,nroots;
53969ce434fSBarry Smith   PetscSFNode    *remote;
54069ce434fSBarry Smith 
54169ce434fSBarry Smith   PetscFunctionBegin;
54269ce434fSBarry Smith   ierr = PetscLayoutGetLocalSize(layout,&nroots);CHKERRQ(ierr);
543785e854fSJed Brown   ierr = PetscMalloc1(nleaves,&remote);CHKERRQ(ierr);
54469ce434fSBarry Smith   for (i=0; i<nleaves; i++) {
54569ce434fSBarry Smith     PetscInt owner = -1;
54669ce434fSBarry Smith     ierr = PetscLayoutFindOwner(layout,iremote[i],&owner);CHKERRQ(ierr);
54769ce434fSBarry Smith     remote[i].rank  = owner;
54869ce434fSBarry Smith     remote[i].index = iremote[i] - layout->range[owner];
54969ce434fSBarry Smith   }
55069ce434fSBarry Smith   ierr = PetscSFSetGraph(sf,nroots,nleaves,ilocal,localmode,remote,PETSC_OWN_POINTER);CHKERRQ(ierr);
55169ce434fSBarry Smith   PetscFunctionReturn(0);
55269ce434fSBarry Smith }
55369ce434fSBarry Smith 
554f92d6284SStefano Zampini /*@
555f92d6284SStefano Zampini   PetscLayoutCompare - Compares two layouts
556f92d6284SStefano Zampini 
557f92d6284SStefano Zampini   Not Collective
558f92d6284SStefano Zampini 
559f92d6284SStefano Zampini   Input Parameters:
560d11c674dSStefano Zampini + mapa - pointer to the first map
561f92d6284SStefano Zampini - mapb - pointer to the second map
562f92d6284SStefano Zampini 
563f92d6284SStefano Zampini   Output Parameters:
564f92d6284SStefano Zampini . congruent - PETSC_TRUE if the two layouts are congruent, PETSC_FALSE otherwise
565f92d6284SStefano Zampini 
566f92d6284SStefano Zampini   Level: beginner
567f92d6284SStefano Zampini 
568f92d6284SStefano Zampini   Notes:
569f92d6284SStefano Zampini 
570f92d6284SStefano Zampini .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
571f92d6284SStefano Zampini           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
572f92d6284SStefano Zampini @*/
573f92d6284SStefano Zampini PetscErrorCode PetscLayoutCompare(PetscLayout mapa,PetscLayout mapb,PetscBool *congruent)
574f92d6284SStefano Zampini {
575f92d6284SStefano Zampini   PetscErrorCode ierr;
576f92d6284SStefano Zampini   PetscMPIInt    sizea,sizeb;
577f92d6284SStefano Zampini 
578f92d6284SStefano Zampini   PetscFunctionBegin;
579f92d6284SStefano Zampini   *congruent = PETSC_FALSE;
580f92d6284SStefano Zampini   ierr = MPI_Comm_size(mapa->comm,&sizea);CHKERRQ(ierr);
581f92d6284SStefano Zampini   ierr = MPI_Comm_size(mapb->comm,&sizeb);CHKERRQ(ierr);
582f92d6284SStefano Zampini   if (mapa->N == mapb->N && mapa->range && mapb->range && sizea == sizeb) {
583f92d6284SStefano Zampini     ierr = PetscMemcmp(mapa->range,mapb->range,(sizea+1)*sizeof(PetscInt),congruent);CHKERRQ(ierr);
584f92d6284SStefano Zampini   }
585f92d6284SStefano Zampini   PetscFunctionReturn(0);
586f92d6284SStefano Zampini }
587a72d46e8SStefano Zampini 
588a72d46e8SStefano Zampini /* TODO: handle nooffprocentries like MatZeroRowsMapLocal_Private, since this code is the same */
589a72d46e8SStefano Zampini PetscErrorCode PetscLayoutMapLocal(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
590a72d46e8SStefano Zampini {
591a72d46e8SStefano Zampini   PetscInt      *owners = map->range;
592a72d46e8SStefano Zampini   PetscInt       n      = map->n;
593a72d46e8SStefano Zampini   PetscSF        sf;
594a72d46e8SStefano Zampini   PetscInt      *lidxs,*work = NULL;
595a72d46e8SStefano Zampini   PetscSFNode   *ridxs;
596a72d46e8SStefano Zampini   PetscMPIInt    rank;
597a72d46e8SStefano Zampini   PetscInt       r, p = 0, len = 0;
598a72d46e8SStefano Zampini   PetscErrorCode ierr;
599a72d46e8SStefano Zampini 
600a72d46e8SStefano Zampini   PetscFunctionBegin;
601a72d46e8SStefano Zampini   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
602a72d46e8SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs */
603a72d46e8SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
604a72d46e8SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
605a72d46e8SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
606a72d46e8SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
607a72d46e8SStefano Zampini   for (r = 0; r < N; ++r) {
608a72d46e8SStefano Zampini     const PetscInt idx = idxs[r];
609a72d46e8SStefano 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);
610a72d46e8SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
611a72d46e8SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
612a72d46e8SStefano Zampini     }
613a72d46e8SStefano Zampini     ridxs[r].rank = p;
614a72d46e8SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
615a72d46e8SStefano Zampini   }
616a72d46e8SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
617a72d46e8SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
618a72d46e8SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
619a72d46e8SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
620a72d46e8SStefano Zampini   if (ogidxs) { /* communicate global idxs */
621a72d46e8SStefano Zampini     PetscInt cum = 0,start,*work2;
622a72d46e8SStefano Zampini 
623a72d46e8SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
624a72d46e8SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
625a72d46e8SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
626a72d46e8SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
627a72d46e8SStefano Zampini     start -= cum;
628a72d46e8SStefano Zampini     cum = 0;
629a72d46e8SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
630a72d46e8SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
631a72d46e8SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
632a72d46e8SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
633a72d46e8SStefano Zampini   }
634a72d46e8SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
635a72d46e8SStefano Zampini   /* Compress and put in indices */
636a72d46e8SStefano Zampini   for (r = 0; r < n; ++r)
637a72d46e8SStefano Zampini     if (lidxs[r] >= 0) {
638a72d46e8SStefano Zampini       if (work) work[len] = work[r];
639a72d46e8SStefano Zampini       lidxs[len++] = r;
640a72d46e8SStefano Zampini     }
641a72d46e8SStefano Zampini   if (on) *on = len;
642a72d46e8SStefano Zampini   if (oidxs) *oidxs = lidxs;
643a72d46e8SStefano Zampini   if (ogidxs) *ogidxs = work;
644a72d46e8SStefano Zampini   PetscFunctionReturn(0);
645a72d46e8SStefano Zampini }
646