xref: /petsc/src/sys/utils/psplit.c (revision d8e47b638cf8f604a99e9678e1df24f82d959cd7)
1c6db04a5SJed Brown #include <petscsys.h> /*I    "petscsys.h" I*/
2e5c89e4eSSatish Balay 
3e30d2299SSatish Balay /*@
4e5c89e4eSSatish Balay   PetscSplitOwnershipBlock - Given a global (or local) length determines a local
5e5c89e4eSSatish Balay   (or global) length via a simple formula. Splits so each processors local size
6e5c89e4eSSatish Balay   is divisible by the block size.
7e5c89e4eSSatish Balay 
8667f096bSBarry Smith   Collective (if `N` is `PETSC_DECIDE`)
9e5c89e4eSSatish Balay 
10e5c89e4eSSatish Balay   Input Parameters:
11e5c89e4eSSatish Balay + comm - MPI communicator that shares the object being divided
12e5c89e4eSSatish Balay . bs   - block size
13811af0c4SBarry Smith . n    - local length (or `PETSC_DECIDE` to have it set)
14811af0c4SBarry Smith - N    - global length (or `PETSC_DECIDE`)
15e5c89e4eSSatish Balay 
16e5c89e4eSSatish Balay   Level: developer
17e5c89e4eSSatish Balay 
18e5c89e4eSSatish Balay   Notes:
19667f096bSBarry Smith   `n` and `N` cannot be both `PETSC_DECIDE`
20e5c89e4eSSatish Balay 
21667f096bSBarry Smith   If one processor calls this with `N` of `PETSC_DECIDE` then all processors
22e5c89e4eSSatish Balay   must, otherwise the program will hang.
23e5c89e4eSSatish Balay 
24811af0c4SBarry Smith .seealso: `PetscSplitOwnership()`, `PetscSplitOwnershipEqual()`
25e5c89e4eSSatish Balay @*/
PetscSplitOwnershipBlock(MPI_Comm comm,PetscInt bs,PetscInt * n,PetscInt * N)26d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSplitOwnershipBlock(MPI_Comm comm, PetscInt bs, PetscInt *n, PetscInt *N)
27d71ae5a4SJacob Faibussowitsch {
28e5c89e4eSSatish Balay   PetscMPIInt size, rank;
29e5c89e4eSSatish Balay 
30e5c89e4eSSatish Balay   PetscFunctionBegin;
31cc73adaaSBarry Smith   PetscCheck(*N != PETSC_DECIDE || *n != PETSC_DECIDE, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Both n and N cannot be PETSC_DECIDE");
32e5c89e4eSSatish Balay 
33e5c89e4eSSatish Balay   if (*N == PETSC_DECIDE) {
3408401ef6SPierre 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);
35*462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(n, N, 1, MPIU_INT, MPI_SUM, comm));
36e5c89e4eSSatish Balay   } else if (*n == PETSC_DECIDE) {
37e5c89e4eSSatish Balay     PetscInt Nbs = *N / bs;
389566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
399566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
40e5c89e4eSSatish Balay     *n = bs * (Nbs / size + ((Nbs % size) > rank));
41e5c89e4eSSatish Balay   }
423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43e5c89e4eSSatish Balay }
44e5c89e4eSSatish Balay 
45e30d2299SSatish Balay /*@
46e5c89e4eSSatish Balay   PetscSplitOwnership - Given a global (or local) length determines a local
47e5c89e4eSSatish Balay   (or global) length via a simple formula
48e5c89e4eSSatish Balay 
49b3480c81SBarry Smith   Collective (if `n` or `N` is `PETSC_DECIDE` or `PETSC_DETERMINE`)
50e5c89e4eSSatish Balay 
51e5c89e4eSSatish Balay   Input Parameters:
52e5c89e4eSSatish Balay + comm - MPI communicator that shares the object being divided
53811af0c4SBarry Smith . n    - local length (or `PETSC_DECIDE` to have it set)
54b3480c81SBarry Smith - N    - global length (or `PETSC_DETERMINE` to have it set)
55e5c89e4eSSatish Balay 
56e5c89e4eSSatish Balay   Level: developer
57e5c89e4eSSatish Balay 
58e5c89e4eSSatish Balay   Notes:
59b3480c81SBarry Smith   `n` and `N` cannot be both `PETSC_DECIDE` and `PETSC_DETERMINE`
60e5c89e4eSSatish Balay 
61b3480c81SBarry Smith   If one processor calls this with `n` of `PETSC_DECIDE` (or with `N` `PETSC_DETERMINE`) then all processors
620e9ea286SStefano Zampini   must. Otherwise, an error is thrown in debug mode while the program will hang
630e9ea286SStefano Zampini   in optimized (i.e. configured --with-debugging=0) mode.
64e5c89e4eSSatish Balay 
65b3480c81SBarry Smith .seealso: `PetscSplitOwnershipBlock()`, `PetscSplitOwnershipEqual()`, `PETSC_DECIDE`, `PETSC_DETERMINE`
66e5c89e4eSSatish Balay @*/
PetscSplitOwnership(MPI_Comm comm,PetscInt * n,PetscInt * N)67d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSplitOwnership(MPI_Comm comm, PetscInt *n, PetscInt *N)
68d71ae5a4SJacob Faibussowitsch {
69e5c89e4eSSatish Balay   PetscMPIInt size, rank;
70e5c89e4eSSatish Balay 
71e5c89e4eSSatish Balay   PetscFunctionBegin;
7200045ab3SPierre Jolivet   PetscCheck(*N != PETSC_DECIDE || *n != PETSC_DECIDE, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Both n and N cannot be PETSC_DECIDE, likely a call to VecSetSizes() or MatSetSizes() is wrong. See https://petsc.org/release/faq/#split-ownership");
7376bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
740e9ea286SStefano Zampini     PetscMPIInt l[2], g[2];
750e9ea286SStefano Zampini     l[0] = (*n == PETSC_DECIDE) ? 1 : 0;
760e9ea286SStefano Zampini     l[1] = (*N == PETSC_DECIDE) ? 1 : 0;
779566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
78*462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(l, g, 2, MPI_INT, MPI_SUM, comm));
79cc73adaaSBarry Smith     PetscCheck(!g[0] || g[0] == size, comm, PETSC_ERR_ARG_INCOMP, "All processes must supply PETSC_DECIDE for local size");
80cc73adaaSBarry Smith     PetscCheck(!g[1] || g[1] == size, comm, PETSC_ERR_ARG_INCOMP, "All processes must supply PETSC_DECIDE for global size");
810e9ea286SStefano Zampini   }
82e5c89e4eSSatish Balay 
83e5c89e4eSSatish Balay   if (*N == PETSC_DECIDE) {
84*462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(n, N, 1, MPIU_INT, MPI_SUM, comm));
85e5c89e4eSSatish Balay   } else if (*n == PETSC_DECIDE) {
869566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
879566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
88e5c89e4eSSatish Balay     *n = *N / size + ((*N % size) > rank);
8976bd3646SJed Brown   } else if (PetscDefined(USE_DEBUG)) {
90e5c89e4eSSatish Balay     PetscInt tmp;
91*462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(n, &tmp, 1, MPIU_INT, MPI_SUM, comm));
9200045ab3SPierre 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 ", likely a call to VecSetSizes() or MatSetSizes() is wrong. See https://petsc.org/release/faq/#split-ownership", tmp, *N, *n);
93e5c89e4eSSatish Balay   }
943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
95e5c89e4eSSatish Balay }
96e5c89e4eSSatish Balay 
97d24d4204SJose E. Roman /*@
98d24d4204SJose E. Roman   PetscSplitOwnershipEqual - Given a global (or local) length determines a local
99d24d4204SJose E. Roman   (or global) length via a simple formula, trying to have all local lengths equal
100d24d4204SJose E. Roman 
101667f096bSBarry Smith   Collective (if `n` or `N` is `PETSC_DECIDE`)
102d24d4204SJose E. Roman 
103d24d4204SJose E. Roman   Input Parameters:
104d24d4204SJose E. Roman + comm - MPI communicator that shares the object being divided
105811af0c4SBarry Smith . n    - local length (or `PETSC_DECIDE` to have it set)
106811af0c4SBarry Smith - N    - global length (or `PETSC_DECIDE`)
107d24d4204SJose E. Roman 
108d24d4204SJose E. Roman   Level: developer
109d24d4204SJose E. Roman 
110d24d4204SJose E. Roman   Notes:
111811af0c4SBarry Smith   This is intended to be used with `MATSCALAPACK`, where the local size must
112d24d4204SJose E. Roman   be equal in all processes (except possibly the last one). For instance,
113667f096bSBarry Smith   the local sizes when splitting `N`=50 with 6 processes are 9,9,9,9,9,5
114d24d4204SJose E. Roman 
115811af0c4SBarry Smith   n and N cannot be both `PETSC_DECIDE`
116d24d4204SJose E. Roman 
117667f096bSBarry Smith   If one processor calls this with `n` or `N` of `PETSC_DECIDE` then all processors
118d24d4204SJose E. Roman   must. Otherwise, an error is thrown in debug mode while the program will hang
119d24d4204SJose E. Roman   in optimized (i.e. configured --with-debugging=0) mode.
120d24d4204SJose E. Roman 
121db781477SPatrick Sanan .seealso: `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`
122d24d4204SJose E. Roman @*/
PetscSplitOwnershipEqual(MPI_Comm comm,PetscInt * n,PetscInt * N)123d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSplitOwnershipEqual(MPI_Comm comm, PetscInt *n, PetscInt *N)
124d71ae5a4SJacob Faibussowitsch {
125d24d4204SJose E. Roman   PetscMPIInt size, rank;
126d24d4204SJose E. Roman 
127d24d4204SJose E. Roman   PetscFunctionBegin;
128cc73adaaSBarry Smith   PetscCheck(*N != PETSC_DECIDE || *n != PETSC_DECIDE, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Both n and N cannot be PETSC_DECIDE");
129d24d4204SJose E. Roman   if (PetscDefined(USE_DEBUG)) {
130d24d4204SJose E. Roman     PetscMPIInt l[2], g[2];
131d24d4204SJose E. Roman     l[0] = (*n == PETSC_DECIDE) ? 1 : 0;
132d24d4204SJose E. Roman     l[1] = (*N == PETSC_DECIDE) ? 1 : 0;
1339566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
134*462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(l, g, 2, MPI_INT, MPI_SUM, comm));
135cc73adaaSBarry Smith     PetscCheck(!g[0] || g[0] == size, comm, PETSC_ERR_ARG_INCOMP, "All processes must supply PETSC_DECIDE for local size");
136cc73adaaSBarry Smith     PetscCheck(!g[1] || g[1] == size, comm, PETSC_ERR_ARG_INCOMP, "All processes must supply PETSC_DECIDE for global size");
137d24d4204SJose E. Roman   }
138d24d4204SJose E. Roman 
139d24d4204SJose E. Roman   if (*N == PETSC_DECIDE) {
140*462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(n, N, 1, MPIU_INT, MPI_SUM, comm));
141d24d4204SJose E. Roman   } else if (*n == PETSC_DECIDE) {
1429566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
1439566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
144d24d4204SJose E. Roman     *n = *N / size;
145d24d4204SJose E. Roman     if (*N % size) {
146d24d4204SJose E. Roman       if ((rank + 1) * (*n + 1) <= *N) *n = *n + 1;
147d24d4204SJose E. Roman       else if (rank * (*n + 1) <= *N) *n = *N - rank * (*n + 1);
148d24d4204SJose E. Roman       else *n = 0;
149d24d4204SJose E. Roman     }
150d24d4204SJose E. Roman   } else if (PetscDefined(USE_DEBUG)) {
151d24d4204SJose E. Roman     PetscInt tmp;
152*462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(n, &tmp, 1, MPIU_INT, MPI_SUM, comm));
15308401ef6SPierre 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);
154d24d4204SJose E. Roman   }
1553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
156d24d4204SJose E. Roman }
157