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