xref: /petsc/src/sys/utils/psplit.c (revision d24d420451aab1d024a728b511d7b61b40627436)
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;
34e32f2f54SBarry Smith   if (*N == PETSC_DECIDE && *n == PETSC_DECIDE) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Both n and N cannot be PETSC_DECIDE");
35e5c89e4eSSatish Balay 
36e5c89e4eSSatish Balay   if (*N == PETSC_DECIDE) {
37e32f2f54SBarry Smith     if (*n % bs != 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"local size %D not divisible by block size %D",*n,bs);
38b2566f29SBarry Smith     ierr = MPIU_Allreduce(n,N,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr);
39e5c89e4eSSatish Balay   } else if (*n == PETSC_DECIDE) {
40e5c89e4eSSatish Balay     PetscInt Nbs = *N/bs;
41e5c89e4eSSatish Balay     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
42e5c89e4eSSatish Balay     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
43e5c89e4eSSatish Balay     *n   = bs*(Nbs/size + ((Nbs % size) > rank));
44e5c89e4eSSatish Balay   }
45e5c89e4eSSatish Balay   PetscFunctionReturn(0);
46e5c89e4eSSatish Balay }
47e5c89e4eSSatish Balay 
48e5c89e4eSSatish Balay 
49e30d2299SSatish Balay /*@
50e5c89e4eSSatish Balay     PetscSplitOwnership - Given a global (or local) length determines a local
51e5c89e4eSSatish Balay         (or global) length via a simple formula
52e5c89e4eSSatish Balay 
53d083f849SBarry Smith    Collective (if n or N is PETSC_DECIDE)
54e5c89e4eSSatish Balay 
55e5c89e4eSSatish Balay    Input Parameters:
56e5c89e4eSSatish Balay +    comm - MPI communicator that shares the object being divided
57e5c89e4eSSatish Balay .    n - local length (or PETSC_DECIDE to have it set)
58e5c89e4eSSatish Balay -    N - global length (or PETSC_DECIDE)
59e5c89e4eSSatish Balay 
60e5c89e4eSSatish Balay   Level: developer
61e5c89e4eSSatish Balay 
62e5c89e4eSSatish Balay    Notes:
63e5c89e4eSSatish Balay      n and N cannot be both PETSC_DECIDE
64e5c89e4eSSatish Balay 
650e9ea286SStefano Zampini      If one processor calls this with n or N of PETSC_DECIDE then all processors
660e9ea286SStefano Zampini      must. Otherwise, an error is thrown in debug mode while the program will hang
670e9ea286SStefano Zampini      in optimized (i.e. configured --with-debugging=0) mode.
68e5c89e4eSSatish Balay 
69e5c89e4eSSatish Balay .seealso: PetscSplitOwnershipBlock()
70e5c89e4eSSatish Balay 
71e5c89e4eSSatish Balay @*/
727087cfbeSBarry Smith PetscErrorCode  PetscSplitOwnership(MPI_Comm comm,PetscInt *n,PetscInt *N)
73e5c89e4eSSatish Balay {
74e5c89e4eSSatish Balay   PetscErrorCode ierr;
75e5c89e4eSSatish Balay   PetscMPIInt    size,rank;
76e5c89e4eSSatish Balay 
77e5c89e4eSSatish Balay   PetscFunctionBegin;
78a8d69d7bSBarry Smith   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 https://www.mcs.anl.gov/petsc/documentation/faq.html#split");
7976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
800e9ea286SStefano Zampini     PetscMPIInt l[2],g[2];
810e9ea286SStefano Zampini     l[0] = (*n == PETSC_DECIDE) ? 1 : 0;
820e9ea286SStefano Zampini     l[1] = (*N == PETSC_DECIDE) ? 1 : 0;
830e9ea286SStefano Zampini     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
840e9ea286SStefano Zampini     ierr = MPIU_Allreduce(l,g,2,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
850e9ea286SStefano Zampini     if (g[0] && g[0] != size) SETERRQ(comm,PETSC_ERR_ARG_INCOMP,"All processes must supply PETSC_DECIDE for local size");
860e9ea286SStefano Zampini     if (g[1] && g[1] != size) SETERRQ(comm,PETSC_ERR_ARG_INCOMP,"All processes must supply PETSC_DECIDE for global size");
870e9ea286SStefano Zampini   }
88e5c89e4eSSatish Balay 
89e5c89e4eSSatish Balay   if (*N == PETSC_DECIDE) {
9081863419SJunchao Zhang     PetscInt64 m = *n, M;
9181863419SJunchao Zhang     ierr = MPIU_Allreduce(&m,&M,1,MPIU_INT64,MPI_SUM,comm);CHKERRQ(ierr);
9281863419SJunchao Zhang     if (M > PETSC_MAX_INT) SETERRQ1(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);
9381863419SJunchao Zhang     else *N = (PetscInt)M;
94e5c89e4eSSatish Balay   } else if (*n == PETSC_DECIDE) {
95e5c89e4eSSatish Balay     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
96e5c89e4eSSatish Balay     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
97e5c89e4eSSatish Balay     *n   = *N/size + ((*N % size) > rank);
9876bd3646SJed Brown   } else if (PetscDefined(USE_DEBUG)) {
99e5c89e4eSSatish Balay     PetscInt tmp;
100b2566f29SBarry Smith     ierr = MPIU_Allreduce(n,&tmp,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr);
101a8d69d7bSBarry Smith     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 https://www.mcs.anl.gov/petsc/documentation/faq.html#split",tmp,*N,*n);
102e5c89e4eSSatish Balay   }
103e5c89e4eSSatish Balay   PetscFunctionReturn(0);
104e5c89e4eSSatish Balay }
105e5c89e4eSSatish Balay 
106*d24d4204SJose E. Roman 
107*d24d4204SJose E. Roman /*@
108*d24d4204SJose E. Roman     PetscSplitOwnershipEqual - Given a global (or local) length determines a local
109*d24d4204SJose E. Roman         (or global) length via a simple formula, trying to have all local lengths equal
110*d24d4204SJose E. Roman 
111*d24d4204SJose E. Roman    Collective (if n or N is PETSC_DECIDE)
112*d24d4204SJose E. Roman 
113*d24d4204SJose E. Roman    Input Parameters:
114*d24d4204SJose E. Roman +    comm - MPI communicator that shares the object being divided
115*d24d4204SJose E. Roman .    n - local length (or PETSC_DECIDE to have it set)
116*d24d4204SJose E. Roman -    N - global length (or PETSC_DECIDE)
117*d24d4204SJose E. Roman 
118*d24d4204SJose E. Roman    Level: developer
119*d24d4204SJose E. Roman 
120*d24d4204SJose E. Roman    Notes:
121*d24d4204SJose E. Roman      This is intended to be used with MATSCALAPACK, where the local size must
122*d24d4204SJose E. Roman      be equal in all processes (except possibly the last one). For instance,
123*d24d4204SJose E. Roman      the local sizes when spliting N=50 with 6 processes are 9,9,9,9,9,5
124*d24d4204SJose E. Roman 
125*d24d4204SJose E. Roman      n and N cannot be both PETSC_DECIDE
126*d24d4204SJose E. Roman 
127*d24d4204SJose E. Roman      If one processor calls this with n or N of PETSC_DECIDE then all processors
128*d24d4204SJose E. Roman      must. Otherwise, an error is thrown in debug mode while the program will hang
129*d24d4204SJose E. Roman      in optimized (i.e. configured --with-debugging=0) mode.
130*d24d4204SJose E. Roman 
131*d24d4204SJose E. Roman .seealso: PetscSplitOwnership(), PetscSplitOwnershipBlock()
132*d24d4204SJose E. Roman 
133*d24d4204SJose E. Roman @*/
134*d24d4204SJose E. Roman PetscErrorCode  PetscSplitOwnershipEqual(MPI_Comm comm,PetscInt *n,PetscInt *N)
135*d24d4204SJose E. Roman {
136*d24d4204SJose E. Roman   PetscErrorCode ierr;
137*d24d4204SJose E. Roman   PetscMPIInt    size,rank;
138*d24d4204SJose E. Roman 
139*d24d4204SJose E. Roman   PetscFunctionBegin;
140*d24d4204SJose E. Roman   if (*N == PETSC_DECIDE && *n == PETSC_DECIDE) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Both n and N cannot be PETSC_DECIDE");
141*d24d4204SJose E. Roman   if (PetscDefined(USE_DEBUG)) {
142*d24d4204SJose E. Roman     PetscMPIInt l[2],g[2];
143*d24d4204SJose E. Roman     l[0] = (*n == PETSC_DECIDE) ? 1 : 0;
144*d24d4204SJose E. Roman     l[1] = (*N == PETSC_DECIDE) ? 1 : 0;
145*d24d4204SJose E. Roman     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
146*d24d4204SJose E. Roman     ierr = MPIU_Allreduce(l,g,2,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
147*d24d4204SJose E. Roman     if (g[0] && g[0] != size) SETERRQ(comm,PETSC_ERR_ARG_INCOMP,"All processes must supply PETSC_DECIDE for local size");
148*d24d4204SJose E. Roman     if (g[1] && g[1] != size) SETERRQ(comm,PETSC_ERR_ARG_INCOMP,"All processes must supply PETSC_DECIDE for global size");
149*d24d4204SJose E. Roman   }
150*d24d4204SJose E. Roman 
151*d24d4204SJose E. Roman   if (*N == PETSC_DECIDE) {
152*d24d4204SJose E. Roman     PetscInt64 m = *n, M;
153*d24d4204SJose E. Roman     ierr = MPIU_Allreduce(&m,&M,1,MPIU_INT64,MPI_SUM,comm);CHKERRQ(ierr);
154*d24d4204SJose E. Roman     if (M > PETSC_MAX_INT) SETERRQ1(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);
155*d24d4204SJose E. Roman     else *N = (PetscInt)M;
156*d24d4204SJose E. Roman   } else if (*n == PETSC_DECIDE) {
157*d24d4204SJose E. Roman     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
158*d24d4204SJose E. Roman     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
159*d24d4204SJose E. Roman     *n = *N/size;
160*d24d4204SJose E. Roman     if (*N % size) {
161*d24d4204SJose E. Roman       if ((rank+1)*(*n+1)<=*N)  *n = *n+1;
162*d24d4204SJose E. Roman       else if (rank*(*n+1)<=*N) *n = *N-rank*(*n+1);
163*d24d4204SJose E. Roman       else *n = 0;
164*d24d4204SJose E. Roman     }
165*d24d4204SJose E. Roman   } else if (PetscDefined(USE_DEBUG)) {
166*d24d4204SJose E. Roman     PetscInt tmp;
167*d24d4204SJose E. Roman     ierr = MPIU_Allreduce(n,&tmp,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr);
168*d24d4204SJose E. Roman     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",tmp,*N,*n);
169*d24d4204SJose E. Roman   }
170*d24d4204SJose E. Roman   PetscFunctionReturn(0);
171*d24d4204SJose E. Roman }
172*d24d4204SJose E. Roman 
173