xref: /petsc/src/sys/utils/psplit.c (revision 2c71b3e237ead271e4f3aa1505f92bf476e3413d)
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