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 9d083f849SBarry 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 14e5c89e4eSSatish Balay . n - local length (or PETSC_DECIDE to have it set) 15e5c89e4eSSatish Balay - N - global length (or PETSC_DECIDE) 16e5c89e4eSSatish Balay 17e5c89e4eSSatish Balay Level: developer 18e5c89e4eSSatish Balay 19e5c89e4eSSatish Balay Notes: 20e5c89e4eSSatish Balay n and N cannot be both PETSC_DECIDE 21e5c89e4eSSatish Balay 22e5c89e4eSSatish Balay If one processor calls this with N of PETSC_DECIDE then all processors 23e5c89e4eSSatish Balay must, otherwise the program will hang. 24e5c89e4eSSatish Balay 25db781477SPatrick Sanan .seealso: `PetscSplitOwnership()` 26e5c89e4eSSatish Balay 27e5c89e4eSSatish Balay @*/ 28*9371c9d4SSatish Balay PetscErrorCode PetscSplitOwnershipBlock(MPI_Comm comm, PetscInt bs, PetscInt *n, PetscInt *N) { 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 } 43e5c89e4eSSatish Balay PetscFunctionReturn(0); 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 50d083f849SBarry 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 54e5c89e4eSSatish Balay . n - local length (or PETSC_DECIDE to have it set) 55e5c89e4eSSatish Balay - N - global length (or PETSC_DECIDE) 56e5c89e4eSSatish Balay 57e5c89e4eSSatish Balay Level: developer 58e5c89e4eSSatish Balay 59e5c89e4eSSatish Balay Notes: 60e5c89e4eSSatish Balay n and N cannot be both PETSC_DECIDE 61e5c89e4eSSatish Balay 620e9ea286SStefano Zampini 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 66db781477SPatrick Sanan .seealso: `PetscSplitOwnershipBlock()` 67e5c89e4eSSatish Balay 68e5c89e4eSSatish Balay @*/ 69*9371c9d4SSatish Balay PetscErrorCode PetscSplitOwnership(MPI_Comm comm, PetscInt *n, PetscInt *N) { 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 } 98e5c89e4eSSatish Balay PetscFunctionReturn(0); 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 105d24d4204SJose E. Roman 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 109d24d4204SJose E. Roman . n - local length (or PETSC_DECIDE to have it set) 110d24d4204SJose E. Roman - N - global length (or PETSC_DECIDE) 111d24d4204SJose E. Roman 112d24d4204SJose E. Roman Level: developer 113d24d4204SJose E. Roman 114d24d4204SJose E. Roman Notes: 115d24d4204SJose E. Roman 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 119d24d4204SJose E. Roman n and N cannot be both PETSC_DECIDE 120d24d4204SJose E. Roman 121d24d4204SJose E. Roman 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 127d24d4204SJose E. Roman @*/ 128*9371c9d4SSatish Balay PetscErrorCode PetscSplitOwnershipEqual(MPI_Comm comm, PetscInt *n, PetscInt *N) { 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 } 162d24d4204SJose E. Roman PetscFunctionReturn(0); 163d24d4204SJose E. Roman } 164