Actual source code: psplit.c
petsc-3.11.4 2019-09-28
2: #include <petscsys.h>
4: /*@
5: PetscSplitOwnershipBlock - Given a global (or local) length determines a local
6: (or global) length via a simple formula. Splits so each processors local size
7: is divisible by the block size.
9: Collective on MPI_Comm (if N is PETSC_DECIDE)
11: Input Parameters:
12: + comm - MPI communicator that shares the object being divided
13: . bs - block size
14: . n - local length (or PETSC_DECIDE to have it set)
15: - N - global length (or PETSC_DECIDE)
17: Level: developer
19: Notes:
20: n and N cannot be both PETSC_DECIDE
22: If one processor calls this with N of PETSC_DECIDE then all processors
23: must, otherwise the program will hang.
25: .seealso: PetscSplitOwnership()
27: @*/
28: PetscErrorCode PetscSplitOwnershipBlock(MPI_Comm comm,PetscInt bs,PetscInt *n,PetscInt *N)
29: {
31: PetscMPIInt size,rank;
34: if (*N == PETSC_DECIDE && *n == PETSC_DECIDE) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Both n and N cannot be PETSC_DECIDE");
36: if (*N == PETSC_DECIDE) {
37: if (*n % bs != 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"local size %D not divisible by block size %D",*n,bs);
38: MPIU_Allreduce(n,N,1,MPIU_INT,MPI_SUM,comm);
39: } else if (*n == PETSC_DECIDE) {
40: PetscInt Nbs = *N/bs;
41: MPI_Comm_size(comm,&size);
42: MPI_Comm_rank(comm,&rank);
43: *n = bs*(Nbs/size + ((Nbs % size) > rank));
44: }
45: return(0);
46: }
49: /*@
50: PetscSplitOwnership - Given a global (or local) length determines a local
51: (or global) length via a simple formula
53: Collective on MPI_Comm (if n or N is PETSC_DECIDE)
55: Input Parameters:
56: + comm - MPI communicator that shares the object being divided
57: . n - local length (or PETSC_DECIDE to have it set)
58: - N - global length (or PETSC_DECIDE)
60: Level: developer
62: Notes:
63: n and N cannot be both PETSC_DECIDE
65: If one processor calls this with n or N of PETSC_DECIDE then all processors
66: must. Otherwise, an error is thrown in debug mode while the program will hang
67: in optimized (i.e. configured --with-debugging=0) mode.
69: .seealso: PetscSplitOwnershipBlock()
71: @*/
72: PetscErrorCode PetscSplitOwnership(MPI_Comm comm,PetscInt *n,PetscInt *N)
73: {
75: PetscMPIInt size,rank;
78: if (*N == PETSC_DECIDE && *n == PETSC_DECIDE) SETERRQ(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 http://www.mcs.anl.gov/petsc/documentation/faq.html#split");
79: #if defined(PETSC_USE_DEBUG)
80: {
81: PetscMPIInt l[2],g[2];
82: l[0] = (*n == PETSC_DECIDE) ? 1 : 0;
83: l[1] = (*N == PETSC_DECIDE) ? 1 : 0;
84: MPI_Comm_size(comm,&size);
85: MPIU_Allreduce(l,g,2,MPI_INT,MPI_SUM,comm);
86: if (g[0] && g[0] != size) SETERRQ(comm,PETSC_ERR_ARG_INCOMP,"All processes must supply PETSC_DECIDE for local size");
87: if (g[1] && g[1] != size) SETERRQ(comm,PETSC_ERR_ARG_INCOMP,"All processes must supply PETSC_DECIDE for global size");
88: }
89: #endif
91: if (*N == PETSC_DECIDE) {
92: MPIU_Allreduce(n,N,1,MPIU_INT,MPI_SUM,comm);
93: } else if (*n == PETSC_DECIDE) {
94: MPI_Comm_size(comm,&size);
95: MPI_Comm_rank(comm,&rank);
96: *n = *N/size + ((*N % size) > rank);
97: #if defined(PETSC_USE_DEBUG)
98: } else {
99: PetscInt tmp;
100: MPIU_Allreduce(n,&tmp,1,MPIU_INT,MPI_SUM,comm);
101: if (tmp != *N) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Sum of local lengths %D does not equal global length %D, my local length %D\n likely a call to VecSetSizes() or MatSetSizes() is wrong.\nSee http://www.mcs.anl.gov/petsc/documentation/faq.html#split",tmp,*N,*n);
102: #endif
103: }
104: return(0);
105: }