xref: /petsc/src/sys/utils/psplit.c (revision 3ba1676111f5c958fe6c2729b46ca4d523958bb3)
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 
9811af0c4SBarry 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
14811af0c4SBarry Smith .    n - local length (or `PETSC_DECIDE` to have it set)
15811af0c4SBarry Smith -    N - global length (or `PETSC_DECIDE`)
16e5c89e4eSSatish Balay 
17e5c89e4eSSatish Balay   Level: developer
18e5c89e4eSSatish Balay 
19e5c89e4eSSatish Balay    Notes:
20811af0c4SBarry Smith      n and N cannot be both `PETSC_DECIDE`
21e5c89e4eSSatish Balay 
22811af0c4SBarry Smith      If one processor calls this with N of `PETSC_DECIDE` then all processors
23e5c89e4eSSatish Balay      must, otherwise the program will hang.
24e5c89e4eSSatish Balay 
25811af0c4SBarry Smith .seealso: `PetscSplitOwnership()`, `PetscSplitOwnershipEqual()`
26e5c89e4eSSatish Balay @*/
27d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSplitOwnershipBlock(MPI_Comm comm, PetscInt bs, PetscInt *n, PetscInt *N)
28d71ae5a4SJacob Faibussowitsch {
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   }
43*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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 
50811af0c4SBarry 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
54811af0c4SBarry Smith .    n - local length (or `PETSC_DECIDE` to have it set)
55811af0c4SBarry Smith -    N - global length (or `PETSC_DECIDE`)
56e5c89e4eSSatish Balay 
57e5c89e4eSSatish Balay   Level: developer
58e5c89e4eSSatish Balay 
59e5c89e4eSSatish Balay    Notes:
60811af0c4SBarry Smith      n and N cannot be both `PETSC_DECIDE`
61e5c89e4eSSatish Balay 
62811af0c4SBarry Smith      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 
66811af0c4SBarry Smith .seealso: `PetscSplitOwnershipBlock()`, `PetscSplitOwnershipEqual()`
67e5c89e4eSSatish Balay @*/
68d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSplitOwnership(MPI_Comm comm, PetscInt *n, PetscInt *N)
69d71ae5a4SJacob Faibussowitsch {
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   }
98*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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 
105811af0c4SBarry Smith    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
109811af0c4SBarry Smith .    n - local length (or `PETSC_DECIDE` to have it set)
110811af0c4SBarry Smith -    N - global length (or `PETSC_DECIDE`)
111d24d4204SJose E. Roman 
112d24d4204SJose E. Roman    Level: developer
113d24d4204SJose E. Roman 
114d24d4204SJose E. Roman    Notes:
115811af0c4SBarry Smith      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 
119811af0c4SBarry Smith      n and N cannot be both `PETSC_DECIDE`
120d24d4204SJose E. Roman 
121811af0c4SBarry Smith      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 @*/
127d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSplitOwnershipEqual(MPI_Comm comm, PetscInt *n, PetscInt *N)
128d71ae5a4SJacob Faibussowitsch {
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   }
162*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
163d24d4204SJose E. Roman }
164