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 @*/ 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); 351c2dc1cbSBarry Smith PetscCall(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 49*b3480c81SBarry 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) 54*b3480c81SBarry Smith - N - global length (or `PETSC_DETERMINE` to have it set) 55e5c89e4eSSatish Balay 56e5c89e4eSSatish Balay Level: developer 57e5c89e4eSSatish Balay 58e5c89e4eSSatish Balay Notes: 59*b3480c81SBarry Smith `n` and `N` cannot be both `PETSC_DECIDE` and `PETSC_DETERMINE` 60e5c89e4eSSatish Balay 61*b3480c81SBarry 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 65*b3480c81SBarry Smith .seealso: `PetscSplitOwnershipBlock()`, `PetscSplitOwnershipEqual()`, `PETSC_DECIDE`, `PETSC_DETERMINE` 66e5c89e4eSSatish Balay @*/ 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)); 781c2dc1cbSBarry Smith PetscCall(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) { 8481863419SJunchao Zhang PetscInt64 m = *n, M; 851c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&m, &M, 1, MPIU_INT64, MPI_SUM, comm)); 8608401ef6SPierre 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); 87f7d195e4SLawrence Mitchell *N = (PetscInt)M; 88e5c89e4eSSatish Balay } else if (*n == PETSC_DECIDE) { 899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 909566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 91e5c89e4eSSatish Balay *n = *N / size + ((*N % size) > rank); 9276bd3646SJed Brown } else if (PetscDefined(USE_DEBUG)) { 93e5c89e4eSSatish Balay PetscInt tmp; 941c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(n, &tmp, 1, MPIU_INT, MPI_SUM, comm)); 9500045ab3SPierre 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); 96e5c89e4eSSatish Balay } 973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 98e5c89e4eSSatish Balay } 99e5c89e4eSSatish Balay 100d24d4204SJose E. Roman /*@ 101d24d4204SJose E. Roman PetscSplitOwnershipEqual - Given a global (or local) length determines a local 102d24d4204SJose E. Roman (or global) length via a simple formula, trying to have all local lengths equal 103d24d4204SJose E. Roman 104667f096bSBarry Smith Collective (if `n` or `N` is `PETSC_DECIDE`) 105d24d4204SJose E. Roman 106d24d4204SJose E. Roman Input Parameters: 107d24d4204SJose E. Roman + comm - MPI communicator that shares the object being divided 108811af0c4SBarry Smith . n - local length (or `PETSC_DECIDE` to have it set) 109811af0c4SBarry Smith - N - global length (or `PETSC_DECIDE`) 110d24d4204SJose E. Roman 111d24d4204SJose E. Roman Level: developer 112d24d4204SJose E. Roman 113d24d4204SJose E. Roman Notes: 114811af0c4SBarry Smith This is intended to be used with `MATSCALAPACK`, where the local size must 115d24d4204SJose E. Roman be equal in all processes (except possibly the last one). For instance, 116667f096bSBarry Smith the local sizes when splitting `N`=50 with 6 processes are 9,9,9,9,9,5 117d24d4204SJose E. Roman 118811af0c4SBarry Smith n and N cannot be both `PETSC_DECIDE` 119d24d4204SJose E. Roman 120667f096bSBarry Smith If one processor calls this with `n` or `N` of `PETSC_DECIDE` then all processors 121d24d4204SJose E. Roman must. Otherwise, an error is thrown in debug mode while the program will hang 122d24d4204SJose E. Roman in optimized (i.e. configured --with-debugging=0) mode. 123d24d4204SJose E. Roman 124db781477SPatrick Sanan .seealso: `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()` 125d24d4204SJose E. Roman @*/ 126d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSplitOwnershipEqual(MPI_Comm comm, PetscInt *n, PetscInt *N) 127d71ae5a4SJacob Faibussowitsch { 128d24d4204SJose E. Roman PetscMPIInt size, rank; 129d24d4204SJose E. Roman 130d24d4204SJose E. Roman PetscFunctionBegin; 131cc73adaaSBarry Smith PetscCheck(*N != PETSC_DECIDE || *n != PETSC_DECIDE, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Both n and N cannot be PETSC_DECIDE"); 132d24d4204SJose E. Roman if (PetscDefined(USE_DEBUG)) { 133d24d4204SJose E. Roman PetscMPIInt l[2], g[2]; 134d24d4204SJose E. Roman l[0] = (*n == PETSC_DECIDE) ? 1 : 0; 135d24d4204SJose E. Roman l[1] = (*N == PETSC_DECIDE) ? 1 : 0; 1369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 1371c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(l, g, 2, MPI_INT, MPI_SUM, comm)); 138cc73adaaSBarry Smith PetscCheck(!g[0] || g[0] == size, comm, PETSC_ERR_ARG_INCOMP, "All processes must supply PETSC_DECIDE for local size"); 139cc73adaaSBarry Smith PetscCheck(!g[1] || g[1] == size, comm, PETSC_ERR_ARG_INCOMP, "All processes must supply PETSC_DECIDE for global size"); 140d24d4204SJose E. Roman } 141d24d4204SJose E. Roman 142d24d4204SJose E. Roman if (*N == PETSC_DECIDE) { 143d24d4204SJose E. Roman PetscInt64 m = *n, M; 1441c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&m, &M, 1, MPIU_INT64, MPI_SUM, comm)); 14508401ef6SPierre 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); 146f7d195e4SLawrence Mitchell *N = (PetscInt)M; 147d24d4204SJose E. Roman } else if (*n == PETSC_DECIDE) { 1489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 1499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 150d24d4204SJose E. Roman *n = *N / size; 151d24d4204SJose E. Roman if (*N % size) { 152d24d4204SJose E. Roman if ((rank + 1) * (*n + 1) <= *N) *n = *n + 1; 153d24d4204SJose E. Roman else if (rank * (*n + 1) <= *N) *n = *N - rank * (*n + 1); 154d24d4204SJose E. Roman else *n = 0; 155d24d4204SJose E. Roman } 156d24d4204SJose E. Roman } else if (PetscDefined(USE_DEBUG)) { 157d24d4204SJose E. Roman PetscInt tmp; 1581c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(n, &tmp, 1, MPIU_INT, MPI_SUM, comm)); 15908401ef6SPierre 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); 160d24d4204SJose E. Roman } 1613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 162d24d4204SJose E. Roman } 163