xref: /petsc/src/sys/utils/psplit.c (revision 08401ef684002a709c6d3db98a0c9f54a8bcf1ec)
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   PetscMPIInt    size,rank;
31e5c89e4eSSatish Balay 
32e5c89e4eSSatish Balay   PetscFunctionBegin;
332c71b3e2SJacob Faibussowitsch   PetscCheckFalse(*N == PETSC_DECIDE && *n == PETSC_DECIDE,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Both n and N cannot be PETSC_DECIDE");
34e5c89e4eSSatish Balay 
35e5c89e4eSSatish Balay   if (*N == PETSC_DECIDE) {
36*08401ef6SPierre Jolivet     PetscCheck(*n % bs == 0,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"local size %" PetscInt_FMT " not divisible by block size %" PetscInt_FMT,*n,bs);
371c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(n,N,1,MPIU_INT,MPI_SUM,comm));
38e5c89e4eSSatish Balay   } else if (*n == PETSC_DECIDE) {
39e5c89e4eSSatish Balay     PetscInt Nbs = *N/bs;
409566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm,&size));
419566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm,&rank));
42e5c89e4eSSatish Balay     *n   = bs*(Nbs/size + ((Nbs % size) > rank));
43e5c89e4eSSatish Balay   }
44e5c89e4eSSatish Balay   PetscFunctionReturn(0);
45e5c89e4eSSatish Balay }
46e5c89e4eSSatish Balay 
47e30d2299SSatish Balay /*@
48e5c89e4eSSatish Balay     PetscSplitOwnership - Given a global (or local) length determines a local
49e5c89e4eSSatish Balay         (or global) length via a simple formula
50e5c89e4eSSatish Balay 
51d083f849SBarry Smith    Collective (if n or N is PETSC_DECIDE)
52e5c89e4eSSatish Balay 
53e5c89e4eSSatish Balay    Input Parameters:
54e5c89e4eSSatish Balay +    comm - MPI communicator that shares the object being divided
55e5c89e4eSSatish Balay .    n - local length (or PETSC_DECIDE to have it set)
56e5c89e4eSSatish Balay -    N - global length (or PETSC_DECIDE)
57e5c89e4eSSatish Balay 
58e5c89e4eSSatish Balay   Level: developer
59e5c89e4eSSatish Balay 
60e5c89e4eSSatish Balay    Notes:
61e5c89e4eSSatish Balay      n and N cannot be both PETSC_DECIDE
62e5c89e4eSSatish Balay 
630e9ea286SStefano Zampini      If one processor calls this with n or N of PETSC_DECIDE then all processors
640e9ea286SStefano Zampini      must. Otherwise, an error is thrown in debug mode while the program will hang
650e9ea286SStefano Zampini      in optimized (i.e. configured --with-debugging=0) mode.
66e5c89e4eSSatish Balay 
67e5c89e4eSSatish Balay .seealso: PetscSplitOwnershipBlock()
68e5c89e4eSSatish Balay 
69e5c89e4eSSatish Balay @*/
707087cfbeSBarry Smith PetscErrorCode  PetscSplitOwnership(MPI_Comm comm,PetscInt *n,PetscInt *N)
71e5c89e4eSSatish Balay {
72e5c89e4eSSatish Balay   PetscMPIInt    size,rank;
73e5c89e4eSSatish Balay 
74e5c89e4eSSatish Balay   PetscFunctionBegin;
752c71b3e2SJacob Faibussowitsch   PetscCheckFalse(*N == PETSC_DECIDE && *n == PETSC_DECIDE,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://petsc.org/release/faq/#split-ownership");
7676bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
770e9ea286SStefano Zampini     PetscMPIInt l[2],g[2];
780e9ea286SStefano Zampini     l[0] = (*n == PETSC_DECIDE) ? 1 : 0;
790e9ea286SStefano Zampini     l[1] = (*N == PETSC_DECIDE) ? 1 : 0;
809566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm,&size));
811c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(l,g,2,MPI_INT,MPI_SUM,comm));
822c71b3e2SJacob Faibussowitsch     PetscCheckFalse(g[0] && g[0] != size,comm,PETSC_ERR_ARG_INCOMP,"All processes must supply PETSC_DECIDE for local size");
832c71b3e2SJacob Faibussowitsch     PetscCheckFalse(g[1] && g[1] != size,comm,PETSC_ERR_ARG_INCOMP,"All processes must supply PETSC_DECIDE for global size");
840e9ea286SStefano Zampini   }
85e5c89e4eSSatish Balay 
86e5c89e4eSSatish Balay   if (*N == PETSC_DECIDE) {
8781863419SJunchao Zhang     PetscInt64 m = *n, M;
881c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&m,&M,1,MPIU_INT64,MPI_SUM,comm));
89*08401ef6SPierre Jolivet     PetscCheck(M <= PETSC_MAX_INT,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);
9081863419SJunchao Zhang     else *N = (PetscInt)M;
91e5c89e4eSSatish Balay   } else if (*n == PETSC_DECIDE) {
929566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm,&size));
939566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm,&rank));
94e5c89e4eSSatish Balay     *n   = *N/size + ((*N % size) > rank);
9576bd3646SJed Brown   } else if (PetscDefined(USE_DEBUG)) {
96e5c89e4eSSatish Balay     PetscInt tmp;
971c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(n,&tmp,1,MPIU_INT,MPI_SUM,comm));
98*08401ef6SPierre Jolivet     PetscCheck(tmp == *N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Sum of local lengths %" PetscInt_FMT " does not equal global length %" PetscInt_FMT ", my local length %" PetscInt_FMT "\n  likely a call to VecSetSizes() or MatSetSizes() is wrong.\nSee https://petsc.org/release/faq/#split-ownership",tmp,*N,*n);
99e5c89e4eSSatish Balay   }
100e5c89e4eSSatish Balay   PetscFunctionReturn(0);
101e5c89e4eSSatish Balay }
102e5c89e4eSSatish Balay 
103d24d4204SJose E. Roman /*@
104d24d4204SJose E. Roman     PetscSplitOwnershipEqual - Given a global (or local) length determines a local
105d24d4204SJose E. Roman         (or global) length via a simple formula, trying to have all local lengths equal
106d24d4204SJose E. Roman 
107d24d4204SJose E. Roman    Collective (if n or N is PETSC_DECIDE)
108d24d4204SJose E. Roman 
109d24d4204SJose E. Roman    Input Parameters:
110d24d4204SJose E. Roman +    comm - MPI communicator that shares the object being divided
111d24d4204SJose E. Roman .    n - local length (or PETSC_DECIDE to have it set)
112d24d4204SJose E. Roman -    N - global length (or PETSC_DECIDE)
113d24d4204SJose E. Roman 
114d24d4204SJose E. Roman    Level: developer
115d24d4204SJose E. Roman 
116d24d4204SJose E. Roman    Notes:
117d24d4204SJose E. Roman      This is intended to be used with MATSCALAPACK, where the local size must
118d24d4204SJose E. Roman      be equal in all processes (except possibly the last one). For instance,
119d24d4204SJose E. Roman      the local sizes when spliting N=50 with 6 processes are 9,9,9,9,9,5
120d24d4204SJose E. Roman 
121d24d4204SJose E. Roman      n and N cannot be both PETSC_DECIDE
122d24d4204SJose E. Roman 
123d24d4204SJose E. Roman      If one processor calls this with n or N of PETSC_DECIDE then all processors
124d24d4204SJose E. Roman      must. Otherwise, an error is thrown in debug mode while the program will hang
125d24d4204SJose E. Roman      in optimized (i.e. configured --with-debugging=0) mode.
126d24d4204SJose E. Roman 
127d24d4204SJose E. Roman .seealso: PetscSplitOwnership(), PetscSplitOwnershipBlock()
128d24d4204SJose E. Roman 
129d24d4204SJose E. Roman @*/
130d24d4204SJose E. Roman PetscErrorCode  PetscSplitOwnershipEqual(MPI_Comm comm,PetscInt *n,PetscInt *N)
131d24d4204SJose E. Roman {
132d24d4204SJose E. Roman   PetscMPIInt    size,rank;
133d24d4204SJose E. Roman 
134d24d4204SJose E. Roman   PetscFunctionBegin;
1352c71b3e2SJacob Faibussowitsch   PetscCheckFalse(*N == PETSC_DECIDE && *n == PETSC_DECIDE,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Both n and N cannot be PETSC_DECIDE");
136d24d4204SJose E. Roman   if (PetscDefined(USE_DEBUG)) {
137d24d4204SJose E. Roman     PetscMPIInt l[2],g[2];
138d24d4204SJose E. Roman     l[0] = (*n == PETSC_DECIDE) ? 1 : 0;
139d24d4204SJose E. Roman     l[1] = (*N == PETSC_DECIDE) ? 1 : 0;
1409566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm,&size));
1411c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(l,g,2,MPI_INT,MPI_SUM,comm));
1422c71b3e2SJacob Faibussowitsch     PetscCheckFalse(g[0] && g[0] != size,comm,PETSC_ERR_ARG_INCOMP,"All processes must supply PETSC_DECIDE for local size");
1432c71b3e2SJacob Faibussowitsch     PetscCheckFalse(g[1] && g[1] != size,comm,PETSC_ERR_ARG_INCOMP,"All processes must supply PETSC_DECIDE for global size");
144d24d4204SJose E. Roman   }
145d24d4204SJose E. Roman 
146d24d4204SJose E. Roman   if (*N == PETSC_DECIDE) {
147d24d4204SJose E. Roman     PetscInt64 m = *n, M;
1481c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&m,&M,1,MPIU_INT64,MPI_SUM,comm));
149*08401ef6SPierre Jolivet     PetscCheck(M <= PETSC_MAX_INT,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);
150d24d4204SJose E. Roman     else *N = (PetscInt)M;
151d24d4204SJose E. Roman   } else if (*n == PETSC_DECIDE) {
1529566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm,&size));
1539566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm,&rank));
154d24d4204SJose E. Roman     *n = *N/size;
155d24d4204SJose E. Roman     if (*N % size) {
156d24d4204SJose E. Roman       if ((rank+1)*(*n+1)<=*N)  *n = *n+1;
157d24d4204SJose E. Roman       else if (rank*(*n+1)<=*N) *n = *N-rank*(*n+1);
158d24d4204SJose E. Roman       else *n = 0;
159d24d4204SJose E. Roman     }
160d24d4204SJose E. Roman   } else if (PetscDefined(USE_DEBUG)) {
161d24d4204SJose E. Roman     PetscInt tmp;
1621c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(n,&tmp,1,MPIU_INT,MPI_SUM,comm));
163*08401ef6SPierre Jolivet     PetscCheck(tmp == *N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Sum of local lengths %" PetscInt_FMT " does not equal global length %" PetscInt_FMT ", my local length %" PetscInt_FMT,tmp,*N,*n);
164d24d4204SJose E. Roman   }
165d24d4204SJose E. Roman   PetscFunctionReturn(0);
166d24d4204SJose E. Roman }
167