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 25e5c89e4eSSatish Balay .seealso: PetscSplitOwnership() 26e5c89e4eSSatish Balay 27e5c89e4eSSatish Balay @*/ 287087cfbeSBarry Smith PetscErrorCode PetscSplitOwnershipBlock(MPI_Comm comm,PetscInt bs,PetscInt *n,PetscInt *N) 29e5c89e4eSSatish Balay { 30e5c89e4eSSatish Balay PetscErrorCode ierr; 31e5c89e4eSSatish Balay PetscMPIInt size,rank; 32e5c89e4eSSatish Balay 33e5c89e4eSSatish Balay PetscFunctionBegin; 34*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(*N == PETSC_DECIDE && *n == PETSC_DECIDE,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Both n and N cannot be PETSC_DECIDE"); 35e5c89e4eSSatish Balay 36e5c89e4eSSatish Balay if (*N == PETSC_DECIDE) { 37*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(*n % bs != 0,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"local size %" PetscInt_FMT " not divisible by block size %" PetscInt_FMT,*n,bs); 38820f2d46SBarry Smith ierr = MPIU_Allreduce(n,N,1,MPIU_INT,MPI_SUM,comm);CHKERRMPI(ierr); 39e5c89e4eSSatish Balay } else if (*n == PETSC_DECIDE) { 40e5c89e4eSSatish Balay PetscInt Nbs = *N/bs; 41ffc4695bSBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr); 42ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 43e5c89e4eSSatish Balay *n = bs*(Nbs/size + ((Nbs % size) > rank)); 44e5c89e4eSSatish Balay } 45e5c89e4eSSatish Balay PetscFunctionReturn(0); 46e5c89e4eSSatish Balay } 47e5c89e4eSSatish Balay 48e30d2299SSatish Balay /*@ 49e5c89e4eSSatish Balay PetscSplitOwnership - Given a global (or local) length determines a local 50e5c89e4eSSatish Balay (or global) length via a simple formula 51e5c89e4eSSatish Balay 52d083f849SBarry Smith Collective (if n or N is PETSC_DECIDE) 53e5c89e4eSSatish Balay 54e5c89e4eSSatish Balay Input Parameters: 55e5c89e4eSSatish Balay + comm - MPI communicator that shares the object being divided 56e5c89e4eSSatish Balay . n - local length (or PETSC_DECIDE to have it set) 57e5c89e4eSSatish Balay - N - global length (or PETSC_DECIDE) 58e5c89e4eSSatish Balay 59e5c89e4eSSatish Balay Level: developer 60e5c89e4eSSatish Balay 61e5c89e4eSSatish Balay Notes: 62e5c89e4eSSatish Balay n and N cannot be both PETSC_DECIDE 63e5c89e4eSSatish Balay 640e9ea286SStefano Zampini If one processor calls this with n or N of PETSC_DECIDE then all processors 650e9ea286SStefano Zampini must. Otherwise, an error is thrown in debug mode while the program will hang 660e9ea286SStefano Zampini in optimized (i.e. configured --with-debugging=0) mode. 67e5c89e4eSSatish Balay 68e5c89e4eSSatish Balay .seealso: PetscSplitOwnershipBlock() 69e5c89e4eSSatish Balay 70e5c89e4eSSatish Balay @*/ 717087cfbeSBarry Smith PetscErrorCode PetscSplitOwnership(MPI_Comm comm,PetscInt *n,PetscInt *N) 72e5c89e4eSSatish Balay { 73e5c89e4eSSatish Balay PetscErrorCode ierr; 74e5c89e4eSSatish Balay PetscMPIInt size,rank; 75e5c89e4eSSatish Balay 76e5c89e4eSSatish Balay PetscFunctionBegin; 77*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(*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"); 7876bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 790e9ea286SStefano Zampini PetscMPIInt l[2],g[2]; 800e9ea286SStefano Zampini l[0] = (*n == PETSC_DECIDE) ? 1 : 0; 810e9ea286SStefano Zampini l[1] = (*N == PETSC_DECIDE) ? 1 : 0; 82ffc4695bSBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr); 83820f2d46SBarry Smith ierr = MPIU_Allreduce(l,g,2,MPI_INT,MPI_SUM,comm);CHKERRMPI(ierr); 84*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(g[0] && g[0] != size,comm,PETSC_ERR_ARG_INCOMP,"All processes must supply PETSC_DECIDE for local size"); 85*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(g[1] && g[1] != size,comm,PETSC_ERR_ARG_INCOMP,"All processes must supply PETSC_DECIDE for global size"); 860e9ea286SStefano Zampini } 87e5c89e4eSSatish Balay 88e5c89e4eSSatish Balay if (*N == PETSC_DECIDE) { 8981863419SJunchao Zhang PetscInt64 m = *n, M; 90820f2d46SBarry Smith ierr = MPIU_Allreduce(&m,&M,1,MPIU_INT64,MPI_SUM,comm);CHKERRMPI(ierr); 91*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(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); 9281863419SJunchao Zhang else *N = (PetscInt)M; 93e5c89e4eSSatish Balay } else if (*n == PETSC_DECIDE) { 94ffc4695bSBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr); 95ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 96e5c89e4eSSatish Balay *n = *N/size + ((*N % size) > rank); 9776bd3646SJed Brown } else if (PetscDefined(USE_DEBUG)) { 98e5c89e4eSSatish Balay PetscInt tmp; 99820f2d46SBarry Smith ierr = MPIU_Allreduce(n,&tmp,1,MPIU_INT,MPI_SUM,comm);CHKERRMPI(ierr); 100*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(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); 101e5c89e4eSSatish Balay } 102e5c89e4eSSatish Balay PetscFunctionReturn(0); 103e5c89e4eSSatish Balay } 104e5c89e4eSSatish Balay 105d24d4204SJose E. Roman /*@ 106d24d4204SJose E. Roman PetscSplitOwnershipEqual - Given a global (or local) length determines a local 107d24d4204SJose E. Roman (or global) length via a simple formula, trying to have all local lengths equal 108d24d4204SJose E. Roman 109d24d4204SJose E. Roman Collective (if n or N is PETSC_DECIDE) 110d24d4204SJose E. Roman 111d24d4204SJose E. Roman Input Parameters: 112d24d4204SJose E. Roman + comm - MPI communicator that shares the object being divided 113d24d4204SJose E. Roman . n - local length (or PETSC_DECIDE to have it set) 114d24d4204SJose E. Roman - N - global length (or PETSC_DECIDE) 115d24d4204SJose E. Roman 116d24d4204SJose E. Roman Level: developer 117d24d4204SJose E. Roman 118d24d4204SJose E. Roman Notes: 119d24d4204SJose E. Roman This is intended to be used with MATSCALAPACK, where the local size must 120d24d4204SJose E. Roman be equal in all processes (except possibly the last one). For instance, 121d24d4204SJose E. Roman the local sizes when spliting N=50 with 6 processes are 9,9,9,9,9,5 122d24d4204SJose E. Roman 123d24d4204SJose E. Roman n and N cannot be both PETSC_DECIDE 124d24d4204SJose E. Roman 125d24d4204SJose E. Roman If one processor calls this with n or N of PETSC_DECIDE then all processors 126d24d4204SJose E. Roman must. Otherwise, an error is thrown in debug mode while the program will hang 127d24d4204SJose E. Roman in optimized (i.e. configured --with-debugging=0) mode. 128d24d4204SJose E. Roman 129d24d4204SJose E. Roman .seealso: PetscSplitOwnership(), PetscSplitOwnershipBlock() 130d24d4204SJose E. Roman 131d24d4204SJose E. Roman @*/ 132d24d4204SJose E. Roman PetscErrorCode PetscSplitOwnershipEqual(MPI_Comm comm,PetscInt *n,PetscInt *N) 133d24d4204SJose E. Roman { 134d24d4204SJose E. Roman PetscErrorCode ierr; 135d24d4204SJose E. Roman PetscMPIInt size,rank; 136d24d4204SJose E. Roman 137d24d4204SJose E. Roman PetscFunctionBegin; 138*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(*N == PETSC_DECIDE && *n == PETSC_DECIDE,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Both n and N cannot be PETSC_DECIDE"); 139d24d4204SJose E. Roman if (PetscDefined(USE_DEBUG)) { 140d24d4204SJose E. Roman PetscMPIInt l[2],g[2]; 141d24d4204SJose E. Roman l[0] = (*n == PETSC_DECIDE) ? 1 : 0; 142d24d4204SJose E. Roman l[1] = (*N == PETSC_DECIDE) ? 1 : 0; 143ffc4695bSBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr); 144820f2d46SBarry Smith ierr = MPIU_Allreduce(l,g,2,MPI_INT,MPI_SUM,comm);CHKERRMPI(ierr); 145*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(g[0] && g[0] != size,comm,PETSC_ERR_ARG_INCOMP,"All processes must supply PETSC_DECIDE for local size"); 146*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(g[1] && g[1] != size,comm,PETSC_ERR_ARG_INCOMP,"All processes must supply PETSC_DECIDE for global size"); 147d24d4204SJose E. Roman } 148d24d4204SJose E. Roman 149d24d4204SJose E. Roman if (*N == PETSC_DECIDE) { 150d24d4204SJose E. Roman PetscInt64 m = *n, M; 151820f2d46SBarry Smith ierr = MPIU_Allreduce(&m,&M,1,MPIU_INT64,MPI_SUM,comm);CHKERRMPI(ierr); 152*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(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); 153d24d4204SJose E. Roman else *N = (PetscInt)M; 154d24d4204SJose E. Roman } else if (*n == PETSC_DECIDE) { 155ffc4695bSBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr); 156ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 157d24d4204SJose E. Roman *n = *N/size; 158d24d4204SJose E. Roman if (*N % size) { 159d24d4204SJose E. Roman if ((rank+1)*(*n+1)<=*N) *n = *n+1; 160d24d4204SJose E. Roman else if (rank*(*n+1)<=*N) *n = *N-rank*(*n+1); 161d24d4204SJose E. Roman else *n = 0; 162d24d4204SJose E. Roman } 163d24d4204SJose E. Roman } else if (PetscDefined(USE_DEBUG)) { 164d24d4204SJose E. Roman PetscInt tmp; 165820f2d46SBarry Smith ierr = MPIU_Allreduce(n,&tmp,1,MPIU_INT,MPI_SUM,comm);CHKERRMPI(ierr); 166*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(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); 167d24d4204SJose E. Roman } 168d24d4204SJose E. Roman PetscFunctionReturn(0); 169d24d4204SJose E. Roman } 170