xref: /petsc/src/sys/utils/psplit.c (revision 820f2d463ad7e8160c4f507e09c88f621629a79d)
1e5c89e4eSSatish Balay 
2c6db04a5SJed Brown #include <petscsys.h>           /*I    "petscsys.h" I*/
3e5c89e4eSSatish Balay 
4e30d2299SSatish Balay /*@
5e5c89e4eSSatish Balay     PetscSplitOwnershipBlock - Given a global (or local) length determines a local
6e5c89e4eSSatish Balay         (or global) length via a simple formula. Splits so each processors local size
7e5c89e4eSSatish Balay         is divisible by the block size.
8e5c89e4eSSatish Balay 
9d083f849SBarry Smith    Collective (if N is PETSC_DECIDE)
10e5c89e4eSSatish Balay 
11e5c89e4eSSatish Balay    Input Parameters:
12e5c89e4eSSatish Balay +    comm - MPI communicator that shares the object being divided
13e5c89e4eSSatish Balay .    bs - block size
14e5c89e4eSSatish Balay .    n - local length (or PETSC_DECIDE to have it set)
15e5c89e4eSSatish Balay -    N - global length (or PETSC_DECIDE)
16e5c89e4eSSatish Balay 
17e5c89e4eSSatish Balay   Level: developer
18e5c89e4eSSatish Balay 
19e5c89e4eSSatish Balay    Notes:
20e5c89e4eSSatish Balay      n and N cannot be both PETSC_DECIDE
21e5c89e4eSSatish Balay 
22e5c89e4eSSatish Balay      If one processor calls this with N of PETSC_DECIDE then all processors
23e5c89e4eSSatish Balay      must, otherwise the program will hang.
24e5c89e4eSSatish Balay 
25e5c89e4eSSatish Balay .seealso: PetscSplitOwnership()
26e5c89e4eSSatish Balay 
27e5c89e4eSSatish Balay @*/
287087cfbeSBarry Smith PetscErrorCode  PetscSplitOwnershipBlock(MPI_Comm comm,PetscInt bs,PetscInt *n,PetscInt *N)
29e5c89e4eSSatish Balay {
30e5c89e4eSSatish Balay   PetscErrorCode ierr;
31e5c89e4eSSatish Balay   PetscMPIInt    size,rank;
32e5c89e4eSSatish Balay 
33e5c89e4eSSatish Balay   PetscFunctionBegin;
34e32f2f54SBarry Smith   if (*N == PETSC_DECIDE && *n == PETSC_DECIDE) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Both n and N cannot be PETSC_DECIDE");
35e5c89e4eSSatish Balay 
36e5c89e4eSSatish Balay   if (*N == PETSC_DECIDE) {
37e32f2f54SBarry Smith     if (*n % bs != 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"local size %D not divisible by block size %D",*n,bs);
38*820f2d46SBarry Smith     ierr = MPIU_Allreduce(n,N,1,MPIU_INT,MPI_SUM,comm);CHKERRMPI(ierr);
39e5c89e4eSSatish Balay   } else if (*n == PETSC_DECIDE) {
40e5c89e4eSSatish Balay     PetscInt Nbs = *N/bs;
41ffc4695bSBarry Smith     ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
42ffc4695bSBarry Smith     ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
43e5c89e4eSSatish Balay     *n   = bs*(Nbs/size + ((Nbs % size) > rank));
44e5c89e4eSSatish Balay   }
45e5c89e4eSSatish Balay   PetscFunctionReturn(0);
46e5c89e4eSSatish Balay }
47e5c89e4eSSatish Balay 
48e5c89e4eSSatish Balay 
49e30d2299SSatish Balay /*@
50e5c89e4eSSatish Balay     PetscSplitOwnership - Given a global (or local) length determines a local
51e5c89e4eSSatish Balay         (or global) length via a simple formula
52e5c89e4eSSatish Balay 
53d083f849SBarry Smith    Collective (if n or N is PETSC_DECIDE)
54e5c89e4eSSatish Balay 
55e5c89e4eSSatish Balay    Input Parameters:
56e5c89e4eSSatish Balay +    comm - MPI communicator that shares the object being divided
57e5c89e4eSSatish Balay .    n - local length (or PETSC_DECIDE to have it set)
58e5c89e4eSSatish Balay -    N - global length (or PETSC_DECIDE)
59e5c89e4eSSatish Balay 
60e5c89e4eSSatish Balay   Level: developer
61e5c89e4eSSatish Balay 
62e5c89e4eSSatish Balay    Notes:
63e5c89e4eSSatish Balay      n and N cannot be both PETSC_DECIDE
64e5c89e4eSSatish Balay 
650e9ea286SStefano Zampini      If one processor calls this with n or N of PETSC_DECIDE then all processors
660e9ea286SStefano Zampini      must. Otherwise, an error is thrown in debug mode while the program will hang
670e9ea286SStefano Zampini      in optimized (i.e. configured --with-debugging=0) mode.
68e5c89e4eSSatish Balay 
69e5c89e4eSSatish Balay .seealso: PetscSplitOwnershipBlock()
70e5c89e4eSSatish Balay 
71e5c89e4eSSatish Balay @*/
727087cfbeSBarry Smith PetscErrorCode  PetscSplitOwnership(MPI_Comm comm,PetscInt *n,PetscInt *N)
73e5c89e4eSSatish Balay {
74e5c89e4eSSatish Balay   PetscErrorCode ierr;
75e5c89e4eSSatish Balay   PetscMPIInt    size,rank;
76e5c89e4eSSatish Balay 
77e5c89e4eSSatish Balay   PetscFunctionBegin;
78a8d69d7bSBarry Smith   if (*N == PETSC_DECIDE && *n == PETSC_DECIDE) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Both n and N cannot be PETSC_DECIDE\n  likely a call to VecSetSizes() or MatSetSizes() is wrong.\nSee https://www.mcs.anl.gov/petsc/documentation/faq.html#split");
7976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
800e9ea286SStefano Zampini     PetscMPIInt l[2],g[2];
810e9ea286SStefano Zampini     l[0] = (*n == PETSC_DECIDE) ? 1 : 0;
820e9ea286SStefano Zampini     l[1] = (*N == PETSC_DECIDE) ? 1 : 0;
83ffc4695bSBarry Smith     ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
84*820f2d46SBarry Smith     ierr = MPIU_Allreduce(l,g,2,MPI_INT,MPI_SUM,comm);CHKERRMPI(ierr);
850e9ea286SStefano Zampini     if (g[0] && g[0] != size) SETERRQ(comm,PETSC_ERR_ARG_INCOMP,"All processes must supply PETSC_DECIDE for local size");
860e9ea286SStefano Zampini     if (g[1] && g[1] != size) SETERRQ(comm,PETSC_ERR_ARG_INCOMP,"All processes must supply PETSC_DECIDE for global size");
870e9ea286SStefano Zampini   }
88e5c89e4eSSatish Balay 
89e5c89e4eSSatish Balay   if (*N == PETSC_DECIDE) {
9081863419SJunchao Zhang     PetscInt64 m = *n, M;
91*820f2d46SBarry Smith     ierr = MPIU_Allreduce(&m,&M,1,MPIU_INT64,MPI_SUM,comm);CHKERRMPI(ierr);
9281863419SJunchao Zhang     if (M > PETSC_MAX_INT) SETERRQ1(comm,PETSC_ERR_INT_OVERFLOW,"Global size overflow %" PetscInt64_FMT ". You may consider ./configure PETSc with --with-64-bit-indices for the case you are running", M);
9381863419SJunchao Zhang     else *N = (PetscInt)M;
94e5c89e4eSSatish Balay   } else if (*n == PETSC_DECIDE) {
95ffc4695bSBarry Smith     ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
96ffc4695bSBarry Smith     ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
97e5c89e4eSSatish Balay     *n   = *N/size + ((*N % size) > rank);
9876bd3646SJed Brown   } else if (PetscDefined(USE_DEBUG)) {
99e5c89e4eSSatish Balay     PetscInt tmp;
100*820f2d46SBarry Smith     ierr = MPIU_Allreduce(n,&tmp,1,MPIU_INT,MPI_SUM,comm);CHKERRMPI(ierr);
101a8d69d7bSBarry Smith     if (tmp != *N) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Sum of local lengths %D does not equal global length %D, my local length %D\n  likely a call to VecSetSizes() or MatSetSizes() is wrong.\nSee https://www.mcs.anl.gov/petsc/documentation/faq.html#split",tmp,*N,*n);
102e5c89e4eSSatish Balay   }
103e5c89e4eSSatish Balay   PetscFunctionReturn(0);
104e5c89e4eSSatish Balay }
105e5c89e4eSSatish Balay 
106d24d4204SJose E. Roman 
107d24d4204SJose E. Roman /*@
108d24d4204SJose E. Roman     PetscSplitOwnershipEqual - Given a global (or local) length determines a local
109d24d4204SJose E. Roman         (or global) length via a simple formula, trying to have all local lengths equal
110d24d4204SJose E. Roman 
111d24d4204SJose E. Roman    Collective (if n or N is PETSC_DECIDE)
112d24d4204SJose E. Roman 
113d24d4204SJose E. Roman    Input Parameters:
114d24d4204SJose E. Roman +    comm - MPI communicator that shares the object being divided
115d24d4204SJose E. Roman .    n - local length (or PETSC_DECIDE to have it set)
116d24d4204SJose E. Roman -    N - global length (or PETSC_DECIDE)
117d24d4204SJose E. Roman 
118d24d4204SJose E. Roman    Level: developer
119d24d4204SJose E. Roman 
120d24d4204SJose E. Roman    Notes:
121d24d4204SJose E. Roman      This is intended to be used with MATSCALAPACK, where the local size must
122d24d4204SJose E. Roman      be equal in all processes (except possibly the last one). For instance,
123d24d4204SJose E. Roman      the local sizes when spliting N=50 with 6 processes are 9,9,9,9,9,5
124d24d4204SJose E. Roman 
125d24d4204SJose E. Roman      n and N cannot be both PETSC_DECIDE
126d24d4204SJose E. Roman 
127d24d4204SJose E. Roman      If one processor calls this with n or N of PETSC_DECIDE then all processors
128d24d4204SJose E. Roman      must. Otherwise, an error is thrown in debug mode while the program will hang
129d24d4204SJose E. Roman      in optimized (i.e. configured --with-debugging=0) mode.
130d24d4204SJose E. Roman 
131d24d4204SJose E. Roman .seealso: PetscSplitOwnership(), PetscSplitOwnershipBlock()
132d24d4204SJose E. Roman 
133d24d4204SJose E. Roman @*/
134d24d4204SJose E. Roman PetscErrorCode  PetscSplitOwnershipEqual(MPI_Comm comm,PetscInt *n,PetscInt *N)
135d24d4204SJose E. Roman {
136d24d4204SJose E. Roman   PetscErrorCode ierr;
137d24d4204SJose E. Roman   PetscMPIInt    size,rank;
138d24d4204SJose E. Roman 
139d24d4204SJose E. Roman   PetscFunctionBegin;
140d24d4204SJose E. Roman   if (*N == PETSC_DECIDE && *n == PETSC_DECIDE) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Both n and N cannot be PETSC_DECIDE");
141d24d4204SJose E. Roman   if (PetscDefined(USE_DEBUG)) {
142d24d4204SJose E. Roman     PetscMPIInt l[2],g[2];
143d24d4204SJose E. Roman     l[0] = (*n == PETSC_DECIDE) ? 1 : 0;
144d24d4204SJose E. Roman     l[1] = (*N == PETSC_DECIDE) ? 1 : 0;
145ffc4695bSBarry Smith     ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
146*820f2d46SBarry Smith     ierr = MPIU_Allreduce(l,g,2,MPI_INT,MPI_SUM,comm);CHKERRMPI(ierr);
147d24d4204SJose E. Roman     if (g[0] && g[0] != size) SETERRQ(comm,PETSC_ERR_ARG_INCOMP,"All processes must supply PETSC_DECIDE for local size");
148d24d4204SJose E. Roman     if (g[1] && g[1] != size) SETERRQ(comm,PETSC_ERR_ARG_INCOMP,"All processes must supply PETSC_DECIDE for global size");
149d24d4204SJose E. Roman   }
150d24d4204SJose E. Roman 
151d24d4204SJose E. Roman   if (*N == PETSC_DECIDE) {
152d24d4204SJose E. Roman     PetscInt64 m = *n, M;
153*820f2d46SBarry Smith     ierr = MPIU_Allreduce(&m,&M,1,MPIU_INT64,MPI_SUM,comm);CHKERRMPI(ierr);
154d24d4204SJose E. Roman     if (M > PETSC_MAX_INT) SETERRQ1(comm,PETSC_ERR_INT_OVERFLOW,"Global size overflow %" PetscInt64_FMT ". You may consider ./configure PETSc with --with-64-bit-indices for the case you are running", M);
155d24d4204SJose E. Roman     else *N = (PetscInt)M;
156d24d4204SJose E. Roman   } else if (*n == PETSC_DECIDE) {
157ffc4695bSBarry Smith     ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
158ffc4695bSBarry Smith     ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
159d24d4204SJose E. Roman     *n = *N/size;
160d24d4204SJose E. Roman     if (*N % size) {
161d24d4204SJose E. Roman       if ((rank+1)*(*n+1)<=*N)  *n = *n+1;
162d24d4204SJose E. Roman       else if (rank*(*n+1)<=*N) *n = *N-rank*(*n+1);
163d24d4204SJose E. Roman       else *n = 0;
164d24d4204SJose E. Roman     }
165d24d4204SJose E. Roman   } else if (PetscDefined(USE_DEBUG)) {
166d24d4204SJose E. Roman     PetscInt tmp;
167*820f2d46SBarry Smith     ierr = MPIU_Allreduce(n,&tmp,1,MPIU_INT,MPI_SUM,comm);CHKERRMPI(ierr);
168d24d4204SJose E. Roman     if (tmp != *N) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Sum of local lengths %D does not equal global length %D, my local length %D",tmp,*N,*n);
169d24d4204SJose E. Roman   }
170d24d4204SJose E. Roman   PetscFunctionReturn(0);
171d24d4204SJose E. Roman }
172d24d4204SJose E. Roman 
173