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 9*811af0c4SBarry 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 14*811af0c4SBarry Smith . n - local length (or `PETSC_DECIDE` to have it set) 15*811af0c4SBarry Smith - N - global length (or `PETSC_DECIDE`) 16e5c89e4eSSatish Balay 17e5c89e4eSSatish Balay Level: developer 18e5c89e4eSSatish Balay 19e5c89e4eSSatish Balay Notes: 20*811af0c4SBarry Smith n and N cannot be both `PETSC_DECIDE` 21e5c89e4eSSatish Balay 22*811af0c4SBarry Smith If one processor calls this with N of `PETSC_DECIDE` then all processors 23e5c89e4eSSatish Balay must, otherwise the program will hang. 24e5c89e4eSSatish Balay 25*811af0c4SBarry Smith .seealso: `PetscSplitOwnership()`, `PetscSplitOwnershipEqual()` 26e5c89e4eSSatish Balay @*/ 279371c9d4SSatish Balay PetscErrorCode PetscSplitOwnershipBlock(MPI_Comm comm, PetscInt bs, PetscInt *n, PetscInt *N) { 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 } 42e5c89e4eSSatish Balay PetscFunctionReturn(0); 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*811af0c4SBarry Smith Collective (if n or N is `PETSC_DECIDE`) 50e5c89e4eSSatish Balay 51e5c89e4eSSatish Balay Input Parameters: 52e5c89e4eSSatish Balay + comm - MPI communicator that shares the object being divided 53*811af0c4SBarry Smith . n - local length (or `PETSC_DECIDE` to have it set) 54*811af0c4SBarry Smith - N - global length (or `PETSC_DECIDE`) 55e5c89e4eSSatish Balay 56e5c89e4eSSatish Balay Level: developer 57e5c89e4eSSatish Balay 58e5c89e4eSSatish Balay Notes: 59*811af0c4SBarry Smith n and N cannot be both `PETSC_DECIDE` 60e5c89e4eSSatish Balay 61*811af0c4SBarry Smith If one processor calls this with n or N of `PETSC_DECIDE` 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*811af0c4SBarry Smith .seealso: `PetscSplitOwnershipBlock()`, `PetscSplitOwnershipEqual()` 66e5c89e4eSSatish Balay @*/ 679371c9d4SSatish Balay PetscErrorCode PetscSplitOwnership(MPI_Comm comm, PetscInt *n, PetscInt *N) { 68e5c89e4eSSatish Balay PetscMPIInt size, rank; 69e5c89e4eSSatish Balay 70e5c89e4eSSatish Balay PetscFunctionBegin; 71cc73adaaSBarry 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"); 7276bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 730e9ea286SStefano Zampini PetscMPIInt l[2], g[2]; 740e9ea286SStefano Zampini l[0] = (*n == PETSC_DECIDE) ? 1 : 0; 750e9ea286SStefano Zampini l[1] = (*N == PETSC_DECIDE) ? 1 : 0; 769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 771c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(l, g, 2, MPI_INT, MPI_SUM, comm)); 78cc73adaaSBarry Smith PetscCheck(!g[0] || g[0] == size, comm, PETSC_ERR_ARG_INCOMP, "All processes must supply PETSC_DECIDE for local size"); 79cc73adaaSBarry Smith PetscCheck(!g[1] || g[1] == size, comm, PETSC_ERR_ARG_INCOMP, "All processes must supply PETSC_DECIDE for global size"); 800e9ea286SStefano Zampini } 81e5c89e4eSSatish Balay 82e5c89e4eSSatish Balay if (*N == PETSC_DECIDE) { 8381863419SJunchao Zhang PetscInt64 m = *n, M; 841c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&m, &M, 1, MPIU_INT64, MPI_SUM, comm)); 8508401ef6SPierre 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); 86f7d195e4SLawrence Mitchell *N = (PetscInt)M; 87e5c89e4eSSatish Balay } else if (*n == PETSC_DECIDE) { 889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 90e5c89e4eSSatish Balay *n = *N / size + ((*N % size) > rank); 9176bd3646SJed Brown } else if (PetscDefined(USE_DEBUG)) { 92e5c89e4eSSatish Balay PetscInt tmp; 931c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(n, &tmp, 1, MPIU_INT, MPI_SUM, comm)); 9408401ef6SPierre 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); 95e5c89e4eSSatish Balay } 96e5c89e4eSSatish Balay PetscFunctionReturn(0); 97e5c89e4eSSatish Balay } 98e5c89e4eSSatish Balay 99d24d4204SJose E. Roman /*@ 100d24d4204SJose E. Roman PetscSplitOwnershipEqual - Given a global (or local) length determines a local 101d24d4204SJose E. Roman (or global) length via a simple formula, trying to have all local lengths equal 102d24d4204SJose E. Roman 103*811af0c4SBarry Smith Collective (if n or N is `PETSC_DECIDE`) 104d24d4204SJose E. Roman 105d24d4204SJose E. Roman Input Parameters: 106d24d4204SJose E. Roman + comm - MPI communicator that shares the object being divided 107*811af0c4SBarry Smith . n - local length (or `PETSC_DECIDE` to have it set) 108*811af0c4SBarry Smith - N - global length (or `PETSC_DECIDE`) 109d24d4204SJose E. Roman 110d24d4204SJose E. Roman Level: developer 111d24d4204SJose E. Roman 112d24d4204SJose E. Roman Notes: 113*811af0c4SBarry Smith This is intended to be used with `MATSCALAPACK`, where the local size must 114d24d4204SJose E. Roman be equal in all processes (except possibly the last one). For instance, 115d24d4204SJose E. Roman the local sizes when spliting N=50 with 6 processes are 9,9,9,9,9,5 116d24d4204SJose E. Roman 117*811af0c4SBarry Smith n and N cannot be both `PETSC_DECIDE` 118d24d4204SJose E. Roman 119*811af0c4SBarry Smith If one processor calls this with n or N of `PETSC_DECIDE` then all processors 120d24d4204SJose E. Roman must. Otherwise, an error is thrown in debug mode while the program will hang 121d24d4204SJose E. Roman in optimized (i.e. configured --with-debugging=0) mode. 122d24d4204SJose E. Roman 123db781477SPatrick Sanan .seealso: `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()` 124d24d4204SJose E. Roman @*/ 1259371c9d4SSatish Balay PetscErrorCode PetscSplitOwnershipEqual(MPI_Comm comm, PetscInt *n, PetscInt *N) { 126d24d4204SJose E. Roman PetscMPIInt size, rank; 127d24d4204SJose E. Roman 128d24d4204SJose E. Roman PetscFunctionBegin; 129cc73adaaSBarry Smith PetscCheck(*N != PETSC_DECIDE || *n != PETSC_DECIDE, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Both n and N cannot be PETSC_DECIDE"); 130d24d4204SJose E. Roman if (PetscDefined(USE_DEBUG)) { 131d24d4204SJose E. Roman PetscMPIInt l[2], g[2]; 132d24d4204SJose E. Roman l[0] = (*n == PETSC_DECIDE) ? 1 : 0; 133d24d4204SJose E. Roman l[1] = (*N == PETSC_DECIDE) ? 1 : 0; 1349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 1351c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(l, g, 2, MPI_INT, MPI_SUM, comm)); 136cc73adaaSBarry Smith PetscCheck(!g[0] || g[0] == size, comm, PETSC_ERR_ARG_INCOMP, "All processes must supply PETSC_DECIDE for local size"); 137cc73adaaSBarry Smith PetscCheck(!g[1] || g[1] == size, comm, PETSC_ERR_ARG_INCOMP, "All processes must supply PETSC_DECIDE for global size"); 138d24d4204SJose E. Roman } 139d24d4204SJose E. Roman 140d24d4204SJose E. Roman if (*N == PETSC_DECIDE) { 141d24d4204SJose E. Roman PetscInt64 m = *n, M; 1421c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&m, &M, 1, MPIU_INT64, MPI_SUM, comm)); 14308401ef6SPierre 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); 144f7d195e4SLawrence Mitchell *N = (PetscInt)M; 145d24d4204SJose E. Roman } else if (*n == PETSC_DECIDE) { 1469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 1479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 148d24d4204SJose E. Roman *n = *N / size; 149d24d4204SJose E. Roman if (*N % size) { 150d24d4204SJose E. Roman if ((rank + 1) * (*n + 1) <= *N) *n = *n + 1; 151d24d4204SJose E. Roman else if (rank * (*n + 1) <= *N) *n = *N - rank * (*n + 1); 152d24d4204SJose E. Roman else *n = 0; 153d24d4204SJose E. Roman } 154d24d4204SJose E. Roman } else if (PetscDefined(USE_DEBUG)) { 155d24d4204SJose E. Roman PetscInt tmp; 1561c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(n, &tmp, 1, MPIU_INT, MPI_SUM, comm)); 15708401ef6SPierre 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); 158d24d4204SJose E. Roman } 159d24d4204SJose E. Roman PetscFunctionReturn(0); 160d24d4204SJose E. Roman } 161