xref: /petsc/src/sys/utils/psplit.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
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 
25db781477SPatrick Sanan .seealso: `PetscSplitOwnership()`
26e5c89e4eSSatish Balay 
27e5c89e4eSSatish Balay @*/
28*9371c9d4SSatish Balay PetscErrorCode PetscSplitOwnershipBlock(MPI_Comm comm, PetscInt bs, PetscInt *n, PetscInt *N) {
29e5c89e4eSSatish Balay   PetscMPIInt size, rank;
30e5c89e4eSSatish Balay 
31e5c89e4eSSatish Balay   PetscFunctionBegin;
32cc73adaaSBarry Smith   PetscCheck(*N != PETSC_DECIDE || *n != PETSC_DECIDE, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Both n and N cannot be PETSC_DECIDE");
33e5c89e4eSSatish Balay 
34e5c89e4eSSatish Balay   if (*N == PETSC_DECIDE) {
3508401ef6SPierre 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);
361c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(n, N, 1, MPIU_INT, MPI_SUM, comm));
37e5c89e4eSSatish Balay   } else if (*n == PETSC_DECIDE) {
38e5c89e4eSSatish Balay     PetscInt Nbs = *N / bs;
399566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
409566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
41e5c89e4eSSatish Balay     *n = bs * (Nbs / size + ((Nbs % size) > rank));
42e5c89e4eSSatish Balay   }
43e5c89e4eSSatish Balay   PetscFunctionReturn(0);
44e5c89e4eSSatish Balay }
45e5c89e4eSSatish Balay 
46e30d2299SSatish Balay /*@
47e5c89e4eSSatish Balay     PetscSplitOwnership - Given a global (or local) length determines a local
48e5c89e4eSSatish Balay         (or global) length via a simple formula
49e5c89e4eSSatish Balay 
50d083f849SBarry Smith    Collective (if n or N is PETSC_DECIDE)
51e5c89e4eSSatish Balay 
52e5c89e4eSSatish Balay    Input Parameters:
53e5c89e4eSSatish Balay +    comm - MPI communicator that shares the object being divided
54e5c89e4eSSatish Balay .    n - local length (or PETSC_DECIDE to have it set)
55e5c89e4eSSatish Balay -    N - global length (or PETSC_DECIDE)
56e5c89e4eSSatish Balay 
57e5c89e4eSSatish Balay   Level: developer
58e5c89e4eSSatish Balay 
59e5c89e4eSSatish Balay    Notes:
60e5c89e4eSSatish Balay      n and N cannot be both PETSC_DECIDE
61e5c89e4eSSatish Balay 
620e9ea286SStefano Zampini      If one processor calls this with n or N of PETSC_DECIDE then all processors
630e9ea286SStefano Zampini      must. Otherwise, an error is thrown in debug mode while the program will hang
640e9ea286SStefano Zampini      in optimized (i.e. configured --with-debugging=0) mode.
65e5c89e4eSSatish Balay 
66db781477SPatrick Sanan .seealso: `PetscSplitOwnershipBlock()`
67e5c89e4eSSatish Balay 
68e5c89e4eSSatish Balay @*/
69*9371c9d4SSatish Balay PetscErrorCode PetscSplitOwnership(MPI_Comm comm, PetscInt *n, PetscInt *N) {
70e5c89e4eSSatish Balay   PetscMPIInt size, rank;
71e5c89e4eSSatish Balay 
72e5c89e4eSSatish Balay   PetscFunctionBegin;
73cc73adaaSBarry Smith   PetscCheck(*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");
7476bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
750e9ea286SStefano Zampini     PetscMPIInt l[2], g[2];
760e9ea286SStefano Zampini     l[0] = (*n == PETSC_DECIDE) ? 1 : 0;
770e9ea286SStefano Zampini     l[1] = (*N == PETSC_DECIDE) ? 1 : 0;
789566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
791c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(l, g, 2, MPI_INT, MPI_SUM, comm));
80cc73adaaSBarry Smith     PetscCheck(!g[0] || g[0] == size, comm, PETSC_ERR_ARG_INCOMP, "All processes must supply PETSC_DECIDE for local size");
81cc73adaaSBarry Smith     PetscCheck(!g[1] || g[1] == size, comm, PETSC_ERR_ARG_INCOMP, "All processes must supply PETSC_DECIDE for global size");
820e9ea286SStefano Zampini   }
83e5c89e4eSSatish Balay 
84e5c89e4eSSatish Balay   if (*N == PETSC_DECIDE) {
8581863419SJunchao Zhang     PetscInt64 m = *n, M;
861c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&m, &M, 1, MPIU_INT64, MPI_SUM, comm));
8708401ef6SPierre 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);
88f7d195e4SLawrence Mitchell     *N = (PetscInt)M;
89e5c89e4eSSatish Balay   } else if (*n == PETSC_DECIDE) {
909566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
919566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
92e5c89e4eSSatish Balay     *n = *N / size + ((*N % size) > rank);
9376bd3646SJed Brown   } else if (PetscDefined(USE_DEBUG)) {
94e5c89e4eSSatish Balay     PetscInt tmp;
951c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(n, &tmp, 1, MPIU_INT, MPI_SUM, comm));
9608401ef6SPierre 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);
97e5c89e4eSSatish Balay   }
98e5c89e4eSSatish Balay   PetscFunctionReturn(0);
99e5c89e4eSSatish Balay }
100e5c89e4eSSatish Balay 
101d24d4204SJose E. Roman /*@
102d24d4204SJose E. Roman     PetscSplitOwnershipEqual - Given a global (or local) length determines a local
103d24d4204SJose E. Roman         (or global) length via a simple formula, trying to have all local lengths equal
104d24d4204SJose E. Roman 
105d24d4204SJose E. Roman    Collective (if n or N is PETSC_DECIDE)
106d24d4204SJose E. Roman 
107d24d4204SJose E. Roman    Input Parameters:
108d24d4204SJose E. Roman +    comm - MPI communicator that shares the object being divided
109d24d4204SJose E. Roman .    n - local length (or PETSC_DECIDE to have it set)
110d24d4204SJose E. Roman -    N - global length (or PETSC_DECIDE)
111d24d4204SJose E. Roman 
112d24d4204SJose E. Roman    Level: developer
113d24d4204SJose E. Roman 
114d24d4204SJose E. Roman    Notes:
115d24d4204SJose E. Roman      This is intended to be used with MATSCALAPACK, where the local size must
116d24d4204SJose E. Roman      be equal in all processes (except possibly the last one). For instance,
117d24d4204SJose E. Roman      the local sizes when spliting N=50 with 6 processes are 9,9,9,9,9,5
118d24d4204SJose E. Roman 
119d24d4204SJose E. Roman      n and N cannot be both PETSC_DECIDE
120d24d4204SJose E. Roman 
121d24d4204SJose E. Roman      If one processor calls this with n or N of PETSC_DECIDE then all processors
122d24d4204SJose E. Roman      must. Otherwise, an error is thrown in debug mode while the program will hang
123d24d4204SJose E. Roman      in optimized (i.e. configured --with-debugging=0) mode.
124d24d4204SJose E. Roman 
125db781477SPatrick Sanan .seealso: `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`
126d24d4204SJose E. Roman 
127d24d4204SJose E. Roman @*/
128*9371c9d4SSatish Balay PetscErrorCode PetscSplitOwnershipEqual(MPI_Comm comm, PetscInt *n, PetscInt *N) {
129d24d4204SJose E. Roman   PetscMPIInt size, rank;
130d24d4204SJose E. Roman 
131d24d4204SJose E. Roman   PetscFunctionBegin;
132cc73adaaSBarry Smith   PetscCheck(*N != PETSC_DECIDE || *n != PETSC_DECIDE, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Both n and N cannot be PETSC_DECIDE");
133d24d4204SJose E. Roman   if (PetscDefined(USE_DEBUG)) {
134d24d4204SJose E. Roman     PetscMPIInt l[2], g[2];
135d24d4204SJose E. Roman     l[0] = (*n == PETSC_DECIDE) ? 1 : 0;
136d24d4204SJose E. Roman     l[1] = (*N == PETSC_DECIDE) ? 1 : 0;
1379566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
1381c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(l, g, 2, MPI_INT, MPI_SUM, comm));
139cc73adaaSBarry Smith     PetscCheck(!g[0] || g[0] == size, comm, PETSC_ERR_ARG_INCOMP, "All processes must supply PETSC_DECIDE for local size");
140cc73adaaSBarry Smith     PetscCheck(!g[1] || g[1] == size, comm, PETSC_ERR_ARG_INCOMP, "All processes must supply PETSC_DECIDE for global size");
141d24d4204SJose E. Roman   }
142d24d4204SJose E. Roman 
143d24d4204SJose E. Roman   if (*N == PETSC_DECIDE) {
144d24d4204SJose E. Roman     PetscInt64 m = *n, M;
1451c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&m, &M, 1, MPIU_INT64, MPI_SUM, comm));
14608401ef6SPierre 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);
147f7d195e4SLawrence Mitchell     *N = (PetscInt)M;
148d24d4204SJose E. Roman   } else if (*n == PETSC_DECIDE) {
1499566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
1509566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
151d24d4204SJose E. Roman     *n = *N / size;
152d24d4204SJose E. Roman     if (*N % size) {
153d24d4204SJose E. Roman       if ((rank + 1) * (*n + 1) <= *N) *n = *n + 1;
154d24d4204SJose E. Roman       else if (rank * (*n + 1) <= *N) *n = *N - rank * (*n + 1);
155d24d4204SJose E. Roman       else *n = 0;
156d24d4204SJose E. Roman     }
157d24d4204SJose E. Roman   } else if (PetscDefined(USE_DEBUG)) {
158d24d4204SJose E. Roman     PetscInt tmp;
1591c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(n, &tmp, 1, MPIU_INT, MPI_SUM, comm));
16008401ef6SPierre 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);
161d24d4204SJose E. Roman   }
162d24d4204SJose E. Roman   PetscFunctionReturn(0);
163d24d4204SJose E. Roman }
164